OSerror and socket issues

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
riteman2
Posts: 2
Joined: Thu Jan 16, 2020 5:43 pm

OSerror and socket issues

Post by riteman2 » Mon Feb 03, 2020 4:28 pm

Hello
I have some problems with below program:
The program is to measure the temperature in a fridge, continuously collecting 24 hours of data (one measurement an hour) and show the results using Google Charts on a small webserver running on the ESP8266: In the background a timer is used to blink a LED (Pin13) with 3 different blinkrates dependent on the measured values (Normal, Warning and Alarm).
The HTML looks a bit strange because it was sent through a Minifier to save memory, but the resulting HTML does show the two Charts (a Gauge and an area graph).
If temperature is too high I send an email to Prowl to push a popup to my iPhone.
I am running microPython v1.12 on a WeMos D1mini with a DS18x20 connected via Onewire Pin14).

Now to my problems:
In order to be able to have the webserver running AND have measurements running in the background I have set a timeout on the server - on timeout I close the socket as the program crashed as soon as I tried to send the email: It seems having more sockets open crashes the program? Any ideas how to handle this problem are most welcome!

I get the following error when trying to send the email:
Traceback (most recent call last):
File "<stdin>", line 113, in <module>
File "<stdin>", line 48, in sendMail
File "umail.py", line 30, in __init__
OSError: -2

If it is a memory issue I could split the html page and send the 24 measurements as small parts using conn.send instead of conn.sendall something like this

for j in range(0,24):
conn.send("['"+str(j)+"'," + T[j] + "],")

but am not sure it will help solve the issues as I have not fully understood the use of sockets.
In order to omit having the webserver time out, I also tried to have the timer trigger measurements in the background using a simple scheduler but the program crashed.

The program:

# barebone.py version 0.6

import onewire
import ds18x20
from machine import RTC, Pin, Timer
import network
import urequests as requests
import usocket as socket
import umail

#The list with 24 temperature measurements
T = ["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]

rtc = RTC()

p13 = Pin(13, Pin.OUT)
p13.value(1) # switch off the LED on the board
ledTime = 10
tempLimit = -18
tempRange = 6
allowMail = True
count = 0

WIFI_SSID = 'mySSID'
WIFI_PASS = 'myPW'
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(WIFI_SSID, WIFI_PASS)

while not wifi.isconnected():
pass

print('IP:', wifi.ifconfig()[0])

ow = onewire.OneWire(Pin(14))
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp() # initiate a temp reading

tempStr = "-12"

def blinkLED():
global count
count = (count + 1) % ledTime
if count == 0:
p13.value(not p13.value()) # toggle LED based on ledTime

def sendMail(hour):
smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True)
smtp.login('mymail@gmail.com', 'rtnrwxyzpqrqbhrd')
smtp.to('5db041f82b93blablabla@api.prowlapp.com')
smtp.write("From: Freezer surveilance <mymail@gmail.com>\n")
smtp.write("To: Prowl <5db041f82b7de5291blablabla@api.prowlapp.com>\n")
smtp.write("Subject: ** Warning ** Temperature too high!")
smtp.write("\nTemperatur at {} was " + tempStr +" °C\n".format(hour))
smtp.write("Temperature overview can be seen here: \nhttp://mywebpage.ddns.net")
smtp.send()
smtp.quit()

def setTime():
res=requests.get("http://worldtimeapi.org/api/timezone/Eu ... nhagen.txt") # get LOCAL time as string
startPos =res.text.find("datetime")+10
year = int(res.text[startPos:startPos+4])
month = int(res.text[startPos+5:startPos+7])
day = int(res.text[startPos+8:startPos+10])
hour = int(res.text[startPos+11:startPos+13])
minutes = int(res.text[startPos+14:startPos+16])
seconds = int(res.text[startPos+17:startPos+19])
startPos =res.text.find("day_of_week:")+13
weekday = int(res.text[startPos:startPos+2])
res.close() #CORRECT USE??
rtc.datetime((year, month, day, weekday,hour, minutes, seconds,0)) # set date and time
return hour

hour=setTime()

tim0 = Timer(-1) # construct a virtual timer
tim0.init(period=100, mode=Timer.PERIODIC, callback=lambda t:blinkLED())

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 80))
s.listen(2)
s.settimeout(10) # set to non-blocking mode if 0 - this setting times out in 5 sec

while True:
try:
conn, addr = s.accept()
#print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
request = str(request)
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.send("""<html> <head> <script type="text/javascript" """)
conn.sendall(htmlStr)
conn.close()
except OSError:
s.close() # CORRECT USE??
for rom in roms: # now read the temperature
temp = ds.read_temp(rom)
ds.convert_temp() # initiate a new reading
tempStr = "{:.1f}".format(temp)
#print(tempStr)

if temp <= tempLimit:
ledTime = 10
elif temp <= (tempLimit + tempRange):
ledTime = 5
else:
ledTime = 2

if (temp > tempLimit) and allowMail: # make sure we only send mails once an hour
sendMail(hour,temp)
allowMail = False

if (hour != rtc.datetime()[4]): # we are in a new hour
hour = setTime() # set rtc from Internet clock and update hour
allowMail = True # allow mails to be sent again

T[hour] = tempStr # add new reading as string to the "Today" list of readings
htmlStr = """<html><head><script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript">google.charts.load('current',{'packages':['gauge']}); google.charts.setOnLoadCallback(drawChart1); function drawChart1(){var data1=google.visualization.arrayToDataTable([ ['Label', 'Value'], ['Temperature',""" + tempStr + """]]);
var options1={greenFrom: -30, greenTo: -18, yellowFrom: -18, yellowTo: -12, redFrom:-12, redTo: 30, minorTicks: 5, min: -30, max: 30}; var chart=new google.visualization.Gauge(document.getElementById('chart_div')); chart.draw(data1, options1);}</script> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript">google.charts.load('current',{'packages':['corechart']}); google.charts.setOnLoadCallback(drawChart); function drawChart(){var data=google.visualization.arrayToDataTable( [['Hour', 'Temperature'], ['0',""" + T[0] + """], ['1',""" + T[1] + """], ['2',""" + T[2] + """], ['3',""" + T[3] + """], ['4',""" + T[4] + """], ['5',""" + T[5] + """], ['6',""" + T[6] + """], ['7',""" + T[7] + """], ['8',""" + T[8] + """], ['9',""" + T[9] + """], ['10',""" + T[10] + """], ['11',""" + T[11] + """], ['12',""" + T[12] + """], ['13',""" + T[13] + """], ['14',""" + T[14] + """], ['15',""" + T[15] + """], ['16',""" + T[16] + """], ['17',""" + T[17] + """], ['18',""" + T[18] + """], ['19',""" + T[19] + """], ['20',""" + T[20] + """], ['21',""" + T[21] + """], ['22',""" + T[22] + """], ['23',""" + T[23] + """]]); var options={title: 'Fridge temperature', hAxis:{title: 'Time of Day', titleTextStyle:{color: '#333'}}, vAxis:{minValue: -30}, crosshair:{trigger: 'both'}, animation:{startup: true, duration: 1000, easing: 'out'}}; var chart=new google.visualization.AreaChart(document.getElementById('chart_div1')); chart.draw(data, options);}</script> </head> <body> <div id="chart_div" align='center' style="width: 1200px; height: 300px;"></div><div id="chart_div1" style="width: 1200px; height: 500px;"></div></body> </html>"""
#print(T[hour],hour)
#Create sockert anew
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 80))
s.listen(2)
s.settimeout(10) # set to non-blocking mode if 0 - this setting times out in 5 sec[/i][/i][/i][/i][/i]

Post Reply