Building a webserver on ESP32 using MicroPython - windows-10

Before reading my question, my english skill is poor, so please send me feedback or advise in easy words. Thank you.
What I Want To Do
I want to build a webserver on ESP32-WROOM-32(ESP32-DevKitc_V4) with MicroPython(v1.16 on 2021-06-23: latest firmware available). My Goal is building a webserver inside ESP32 and collecting the data of sensors connected to ESP32 periodically.
Environment
Windows10(64bit)
MicroPython (v1.16 on 2021-06-23)
Editor : Thonny Editor (v3.3.11)
ESP32 Devkitc_v4
ampy (v1.1.0)
What I did
Firstly I wrote a code according to this article : RandomNerdTutorial: ESP32/ESP8266 MicroPython Web Server – Control Outputs. My code is as follows:
import network
import usys
try:
import usocket as socket
except:
import socket
def connect(SSID,PASS):
AP = network.WLAN(network.AP_IF)
if AP.isconnected():
print("Already connected.")
return AP
else:
AP.active(True)
AP.connect(SSID,PASS)
while not AP.isconnected():
print(".",end="")
utime.sleep(0.5)
if AP.isconnected():
print("Network connection is established.")
return AP
else:
print("Connection failed.")
return False
wifi = connect("myssid","mypass")
if not wifi:
usys.exit(0)
html_strings = """
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<title>SERVER TEST</title>
</head>
<body>
<h1>SERVER TEST</h1>
</body>
</html>
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = socket.getaddrinfo(("0,0,0,0",80))[0][-1]
s.bind(addr)
s.listen(1)
print("Linstening on ", addr)
while True:
conn,addr = s.accept()
print("connected from : ",addr)
request = conn.recv(1024)
respose = html_strings
conn.send("HTTP/1.0 200 OK\r\n")
conn.send("Content-type: text/html\r\n")
conn.send("\r\n")
conn.send(response)
conn.close()
I connect ESP32 board with USB cable to PC and Windows10 recognize this device as COM4. I wrote this code on Thonny Editor on windows10(64bit) and then transfer this code as main.py using ampy command on command line like this:
> ampy --port COM4 put main.pye
Tansfer was always successful and then connecting ESP32 from Thonny editor. firstly this message is shown in the shell console like this:
MicroPython v1.16 on 2021-06-23; ESP32 module with ESP32
Type "help()" for more information.
And then when I press reset button on ESP32, Error was shown like this:
Traceback(most recent call last)
File "main.py", line 48, in <module>
TypeError: function mising 1 required positional arguments
The line 48 corresponds this line:
addr = socket.getaddrinfo(("0,0,0,0",80))
According to the official documentation Docs » MicroPython libraries » usocket – socket module,it seems that prividing only two parameters: hostname nad port is enough. I also tried by writing like this:
addr = socket.getaddrinfo(('',80))[#][-1]
But the result was same. I do not understand what is the required another positional argument. So I want advice or feedback to solve this issue.
Thank you for your cooperation.

The getaddrinfo method expects two arguments:
socket.getaddrinfo('hostname', port)
You are passing a single argument -- a 2-tuple. Instead of:
addr = socket.getaddrinfo(("0.0.0.0", 80))
You want:
addr = socket.getaddrinfo("0.0.0.0",80)
Note that I've removed one set of parentheses.
Here's a complete example at the REPL:
>>> import socket
>>> s = socket.socket()
>>> addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
>>> s.bind(addr)
>>> s.listen(1)
>>> conn,addr = s.accept()
>>> addr
('192.168.1.175', 43384)
>>> conn.send('HTTP/1.0 200 OK\r\n')
17
>>> conn.close()

Related

Python Test Code for URL on IP-Address only

I'm a bit lost in Google-results.
I have a webserver running through a Python built-in module.
This works and provides an area to download automation configuration for devices.
However, I like to build an availability test to provide better code.
If http service is not available, then proceed with tftp server.
I tested with urllib2, but then the website gets timed out. If I try the same code with a named uri 'www.google.com' then the response code 200 is provided.
Any thoughts to provide a good solution?
in the code I provide a ping test.
now like to add 'service-available' test. on TRUE - proceed with GET.
should work on IP-ADDRESS eg.: 10.1.1.1:80
Thank you for the help.
code ex:
import httplib2
h = httplib2.Http(".cache")
(resp_headers, content) = h.request("http://10.10.1.1:80/", "GET")
print(resp_headers)
print(content)
Try this. On a successful ping, the script will attempt to connect to an HTTP service. If the request times out or is not successful (e.g., status 404), it will call your TFTP function:
import shlex
import socket
import subprocess
import httplib2
ip_address = "10.1.1.1"
print("Attempting to ping...")
p = subprocess.Popen(shlex.split("ping -c 3 {0}".format(ip_address)), stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, _ = p.communicate()
rc = p.returncode
if rc != 0 or "100% packet loss" in output.decode():
raise RuntimeError("Unable to connect to {0}.".format(ip_address))
print("Ping successful.")
print("Attempting to connect to an HTTP service....")
h = httplib2.Http(cache=".cache", timeout=10)
response = {}
content = ""
try:
response, content = h.request("http://{0}:80".format(ip_address), method="GET")
if 200 <= int(response["status"]) <= 299:
print("Connected to HTTP service.")
for key, value in response.items():
print(key, ":", value)
print(content.decode())
else:
print("Request not OK. Attempting to connect to a TFTP service...")
# Call to TFTP function goes here
except socket.timeout:
print("Request timed out. Attempting to connect to a TFTP service...")
# Call to TFTP function goes here

how to discovery Onvif device with python

In my project, I need to find a camera device that uses the onvif.
I get the desired results through multicast-socket, but it's not as expected.
This is my code:
my_ip = "192.168.1.88"
mul_ip = "239.255.255.250"
mul_port = 37020
xml_str = '<?xml version="1.0" encoding="utf-8"?><Envelope xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns="http://www.w3.org/2003/05/soap-envelope"><Header><wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">uuid:05ebeac7-ab22-4f3c-ac10-71a6bed6788b</wsa:MessageID><wsa:To xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To><wsa:Action xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action></Header><Body><Probe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery"><Types>tds:Device</Types><Scopes /></Probe></Body></Envelope><?xml version="1.0" encoding="utf-8"?><Envelope xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns="http://www.w3.org/2003/05/soap-envelope"><Header><wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">uuid:6604dcab-ae78-4b39-86af-71a3c71884a6</wsa:MessageID><wsa:To xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To><wsa:Action xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action></Header><Body><Probe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery"><Types>dn:NetworkVideoTransmitter</Types><Scopes /></Probe></Body></Envelope>'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
s.bind((my_ip, mul_port))
s.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(mul_ip) + socket.inet_aton(my_ip)
)
s.setblocking(False)
s.sendto(xml_str.encode(), (mul_ip, mul_port))
while True:
try:
data, address = s.recvfrom(65535)
print('address: ', address)
print('data: ', data)
except Exception as e:
pass
This result returns the original xml_str input and my own IP/PORT(my_ip mul_port).
I want to understand two issues:
Is there anything wrong with this python multicast-socket?
Are there other ways to get onvif devices? I used python-ws-discovery (https://github.com/andreikop/python-ws-discovery), but it doesn't work
on Windows10 OS.
I cannot answer the first questions since I'm not that familiar with it multi-socket,
but I can help with the second one.
The code I'm using to discover ONVIF devices in my network (on Windows 10 and macOS)
is as follow:
from wsdiscovery.discovery import ThreadedWSDiscovery as WSDiscovery
from wsdiscovery import Scope
import re
def display(any_list):
for item in any_list:
print(item)
def fetch_devices():
wsd = WSDiscovery()
scope1 = Scope("onvif://www.onvif.org/Profile")
wsd.start()
services = wsd.searchServices(scopes=[scope1])
ipaddresses = []
for service in services:
#filter those devices that dont have ONVIF service
ipaddress = re.search('(\d+|\.)+', str(service.getXAddrs()[0])).group(0)
ipaddresses.append(ipaddress)
print(display(service.getScopes()))
print('----------END')
print(f'\nnumber of devices detected: {len(services)}')
wsd.stop()
return ipaddresses
if __name__ == "__main__":
onvif_devices_IPs = fetch_devices()
display(onvif_devices_IPs)
I'm using the line scope1 = Scope("onvif://www.onvif.org/Profile") to filter and display just those devices with Profiles.

Trying to send data Python CAN

I am using the python can library. I am running the following example code but can not get it to work
from __future__ import print_function
import can
def send_one():
bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000)
msg = can.Message(arbitration_id=0xc0ffee,
data=[0, 25, 0, 1, 3, 1, 4, 1],
is_extended_id=True)
try:
bus.send(msg)
print("Message sent on {}".format(bus.channel_info))
except can.CanError:
print("Message NOT sent")
if __name__ == '__main__':
send_one()
Here is the error message:
OSError: [WinError 10047] An address incompatible with the requested protocol was used
I'm not sure where I am going wrong. I am completely new to using CAN to receive and send data. My current set up for testing this out is as follow:
Laptop -> USB Wire -> CANable Adapter -> CAN Line -> CANable Adapter -> USB Wire -> RaspberryPi
I also can't seem to find any documentation that has clear and concise examples. Thank you to all of those who reply in advance.
Link To Docs: https://buildmedia.readthedocs.org/media/pdf/python-can/develop/python-can.pdf
In your code, you are trying to use the socketcan interface, which is not available on Windows.
Your CANable adapter provides a serial interface. Try the following line:
bus = can.interface.Bus(bustype='serial', channel='COM1', bitrate=250000)
Maybe you have to use a different COM-port-number instead of COM1
Check the python-can documentation chapter CAN over serial for more details.

Aiomas RPC Python 3.6

My goal is to bind TCP RPC server aiomas and clients in different programming languages.
I'm setting the connection, but neither the response from the server nor the response is received.
The documentation says:
https://media.readthedocs.org/pdf/aiomas/1.0.3/aiomas.pdf
Page 26: - On the RPC level, it a three-tuple:
[function, [arg0, arg1, ...], {kwarg0: val0, kwarg1: val1}]
function is a string containing the name of an exposed functions; The type of the arguments and keyword arguments may vary depending on the function.
This simple server:
import aiomas
class Server:
router = aiomas.rpc.Service()
#aiomas.expose
def ping(self, i):
print('Ping receive data: {}'.format(i))
return i
if __name__ == '__main__':
server = aiomas.run(aiomas.rpc.start_server(
('127.0.0.1', 5000),
Server())
)
print('Server run')
aiomas.run(server.wait_closed())
And this my problem tcp client
import socket
import pickle
MESS = ['ping', [1]]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 5000))
s.settimeout(1.5)
s.send(pickle.dumps(MESS))
data = s.recv(1024)
s.close()
Tell me please what's wrong. It is necessary to understand in order to realize this in other languages.Much grateful for any hint
I read the documentation several times, But I did not understand how to compose the header of the package. As a result, I figured out that the last byte is the length of the package. Everything worked.
Here is an example package
data='[0, 0, ["methood", ["args"], {"kwargs":"if exists"}]]'
hex(len(data)) --> 0x35
b'\x00\x00\x00\x35[0, 0, ["methood", ["args"], {"kwargs":"if exists"}]]'

Reading serial port with pymodbus3

I'm working on a serial port using pymodbus3.
When I run the following code the output is 'None'. Whereas I can get response from the device when test for the serial port with modpoll.
How can I fix this issue?
from pymodbus3.client.sync import ModbusSerialClient as mbc
def PortTest(self):
client = mbc(method="rtu", port="/dev/ttyUSB0", stopbits=1, bytesize=8, parity='N', baudrate=9600)
try:
client.connect()
coil = client.read_coils(0, 1)
print(coil)
client.close()
except OSError as err:
raise EnvironmentError(err)
pass
pymodbus3 has a bug. Uninstall it and replace it with the python 3 branch of pymodbus 1.2.0. Go to github and download it.
https://github.com/bashwork/pymodbus/tree/python3

Resources