Guest User

Untitled

a guest
Jan 16th, 2023
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.85 KB | None | 0 0
  1. #!/usr/bin/python3
  2. import time
  3.  
  4. #Make it easier to connect in thonny
  5. print("Hello World")
  6. time.sleep(5)
  7. print("Loading...")
  8.  
  9. from json import dumps as json_encode
  10. from GPIO import GPIO # https://pastebin.com/YX7jDw0E
  11. import _thread
  12. #import uasync_requests as urequest
  13. import urequest # https://github.com/micropython/micropython-lib/blob/master/python-ecosys/urequests/urequests.py
  14. import uasyncio
  15. sleep=uasyncio.sleep
  16. sleep_ms=uasyncio.sleep_ms
  17.  
  18. def http(page,data=False,err=False):
  19.     #return print("Simulation mode: ",page)
  20.     # This function is ugly and i am not happy with it
  21.     if not err:
  22.         page="http://10.0.0.69:8080/"+page
  23.         print("URL =",page,"DATA =",data)
  24.     if not GPIO.nic.isconnected():
  25.         print("----------NO NETWORK----------")
  26.         return False
  27.     try:
  28.         if not data:
  29.             r=urequest.get(page)
  30.         else:
  31.             r=urequest.post(page,data=json_encode(data),headers={"Content-type":"application/json"})
  32.     except BadStatusLine:
  33.         #No idea why my server does this sometimes, line is returned as []
  34.         print("ERROR: BadStatusLine; Ignore")
  35.         r.close()
  36.         r=None
  37.         return True
  38.     except Exception as e:
  39.         print("ERROR:",e)
  40.         if not err:
  41.             time.sleep_ms(500)
  42.             #only try twice
  43.             return http(page,data,True)
  44.         else:
  45.             return False
  46.     if r.status_code == 200 and r.content==b"OK":
  47.         r.close()
  48.         r=True
  49.     else:
  50.         print(page,':',r.status_code,"-",r.content)
  51.         r.close()
  52.         r=False
  53.     return r
  54.  
  55. def polling():
  56.     def counter(x,val):
  57.         if val != x["state"]:
  58.             x["count"]=1
  59.             x["state"]=val
  60.             x["last_time"]=x["time"]
  61.             x["time"]=time.ticks_ms()
  62.         elif x["count"]<GPIO.polling.m_sec:
  63.             x["count"]+=1
  64.         elif x["count"] == GPIO.polling.m_sec:
  65.             return True
  66.         return False
  67.  
  68.     count=[]
  69.     doors=[]
  70.     for i in GPIO.inputs:
  71.         pin=GPIO.inputs[i]
  72.         door=i[-4:]=="door"
  73.         count.append({
  74.             "pin":pin,
  75.             "name":i,
  76.             "state":pin.value(),
  77.             "count":GPIO.polling.m_sec+1,
  78.             "is_door":door,
  79.             "time":0
  80.         })
  81.         if door:
  82.             doors.append({
  83.                 "name":count[-1]["name"],
  84.                 "value":count[-1]["state"]
  85.             })
  86.     doorNotify(doors)
  87.     doors=None
  88.     buzz_ct=0
  89.     while True:
  90.         #START_TIME=time.ticks_us()
  91.         for switch in count:
  92.             val=switch["pin"].value()
  93.             if counter(switch,val):
  94.                 #if not switch["is_door"] and time.ticks_diff(switch["time"],switch["last_time"]) < 1000:# anti-button spam; may never use
  95.                 GPIO.polling.work.append({
  96.                     "name":switch["name"],
  97.                     "is_door":switch["is_door"],
  98.                     "value":val,
  99.                     "time":switch["time"]
  100.                 })
  101.                 switch["count"]+=1
  102.         if GPIO.buzzer.active:# 30 loops = ~50 ms
  103.             buzz_ct+=1
  104.             if buzz_ct==1:
  105.                 GPIO.buzzer.pin.duty_u16(32767)
  106.             elif buzz_ct==30:
  107.                 GPIO.buzzer.pin.duty_u16(0)
  108.             elif buzz_ct==60:
  109.                 buzz_ct=0
  110.         elif buzz_ct:
  111.             buzz_ct=0
  112.             GPIO.buzzer.active=0
  113.             GPIO.buzzer.pin.duty_u16(0)
  114.         time.sleep_ms(1)
  115.         #END_TIME=time.ticks_us()
  116.         #print(time.ticks_diff(END_TIME,START_TIME))
  117.  
  118. async def getWork():
  119.     if not GPIO.polling.work:
  120.         return 0
  121.     job=GPIO.polling.work[0]
  122.     GPIO.polling.work.pop(0)
  123.     #print(GPIO.polling.work,job)
  124.     if job["is_door"]:
  125.         if job["name"] != "living_door" and not job["value"]:
  126.             uasyncio.create_task(lightTimer())
  127.             await sleep(0)
  128.         doorNotify([job])
  129.     elif job["name"] == "garage_button" and job["value"]:
  130.         garageButtons(time.ticks_diff(time.ticks_ms(),job["time"]))
  131.     elif job["name"] == "living_button" and not job["value"]:
  132.         http("music/outputs.php?set=2&pico")
  133.     return 1
  134.  
  135. def readSensor(pin):
  136.     pin.measure()
  137.     data={
  138.         "temp":pin.temperature(),
  139.         "water":pin.humidity()
  140.     }
  141.     print(data)
  142.     if data["temp"]==150.0:
  143.         return False# temp==150.0 and humidity == 100 if read too soon at power up
  144.     else:
  145.         return data
  146.  
  147. async def lightTimer():
  148.     def isBright():
  149.         bright=10000# see notes in GPIO.py
  150.         lighting=GPIO.light.value()
  151.         #print("light level:",lighting, ";threshold:",bright)
  152.         return lighting > bright
  153.  
  154.     if GPIO.light.bulb.value() or isBright():
  155.         return
  156.     sec=30
  157.     GPIO.light.bulb.value(1)
  158.     while sec > 0:
  159.         sec-=1
  160.         if isBright():
  161.             GPIO.light.bulb.value(0)
  162.             GPIO.buzzer.active=0
  163.             return
  164.         if GPIO.light.onboard.value() or not GPIO.light.bulb.value():# light is set manually
  165.             GPIO.buzzer.active=0
  166.             return
  167.         #print("light count down:",sec)
  168.         GPIO.buzzer.active = sec==9 or sec < 3
  169.         await sleep(1)
  170.     GPIO.buzzer.active=0
  171.     print("Timer up, lights out")
  172.     GPIO.light.bulb.value(0)
  173.  
  174. def garageButtons(held):
  175.     pin=GPIO.inputs["garage_button"]
  176.     while pin.value() and held < 750:
  177.         sleep_ms(1)
  178.         held+=1
  179.     if held == 750:# if held was over supplied at over 750 something is VERY wrong, under 100 is expected
  180.         GPIO.light.onboard.toggle()
  181.         GPIO.light.bulb.value(GPIO.light.onboard.value())
  182.     else:
  183.         # http://10.0.0.69:8080/music/outputs.php?set=5
  184.         http("music/outputs.php?set=5&pico")
  185.  
  186. def doorNotify(doors):
  187.     url="smart_home.php?update=garage"
  188.     json={"doors":{},"status":getReadings()}
  189.     for i in doors:
  190.         if i["name"]=="living_door":
  191.             i["value"]=int(not i["value"])
  192.         json["doors"][i["name"]]=i["value"]
  193.     #uasyncio.create_task(http(url,json))
  194.  
  195.     json["status"]=getReadings()
  196.     http(url,json)
  197.  
  198. def getReadings():
  199.     return {
  200.         "bulb": GPIO.light.bulb.value(),
  201.         "onboard": GPIO.light.onboard.value(),
  202.         "light": GPIO.light.value()
  203.     }
  204.  
  205. async def main():
  206.     json={"DHT22":{},"status":{}}
  207.  
  208.     sensors={
  209.         "index":-1,
  210.         "pins":[],
  211.         "names":[],
  212.         "values":[{},{},{},{}],
  213.         "last_index":-1,
  214.         "error":0
  215.     }
  216.     for i in GPIO.sensors:
  217.         sensors["pins"].append(GPIO.sensors[i])
  218.         sensors["names"].append(i)
  219.         sensors["last_index"]+=1
  220.     loops=350000# 3600000 = ~ 15 minutes
  221.     send_data=0
  222.     sensor_error=0
  223.     #debug_msg=0
  224.     while True:
  225.         if await getWork() and loops >= 345000:
  226.             loops=345000
  227.             print("Delay sensor reading")
  228.             # Activity found, defer sensor reading for faster response
  229.         #if GPIO.light.bulb.value() and not GPIO.light.onboard.value():# Timer running
  230.         if send_data:
  231.             send_data=0
  232.             data={}
  233.             for (name,val) in zip(sensors["names"], sensors["values"]):
  234.                 data[name]=val
  235.             http("smart_home.php?update=garage",{
  236.                 "DHT22":data,
  237.                 "status":getReadings()
  238.             })
  239.         elif loops >= 360000 and not GPIO.light.bulb.value():
  240.             # light is off thus no timer
  241.             # Only read one sensor between checks for high priority work
  242.             sensors["index"]+=1
  243.             data=readSensor(sensors["pins"][ sensors["index"] ])
  244.             if data:
  245.                 sensors["values"][ sensors["index"] ]=data
  246.                 sensor_error=0
  247.             elif not sensor_error:
  248.                 # Only try twice
  249.                 sensor_error=1
  250.                 sensors["index"]-=1
  251.                 loops=358000
  252.             #else:#deal with this later
  253.             if sensors["index"] == sensors["last_index"]:
  254.                 loops=0
  255.                 send_data=1
  256.                 sensors["index"]=-1
  257.         await sleep_ms(1)
  258.         loops+=1
  259.         #if debug_msg==10000:
  260.         #   print("alive")
  261.         #   debug_msg=0
  262.         #debug_msg+=1
  263.  
  264. def _main():
  265.     uasyncio.run(main())
  266. print("Starting Work!")
  267. #_thread.start_new_thread(uasyncio.run,(main()))
  268. _thread.start_new_thread(_main,())
  269.  
  270. polling()
  271. print("End of script")
  272.  
Advertisement
Add Comment
Please, Sign In to add comment