/
workMode.py
141 lines (124 loc) · 4.54 KB
/
workMode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import triac # Used for interfacing with the output
import connectionManager as cm
import machine
import time
import sys
import boot
checkFrequency = 200 # Time in ms between each check operation
# Time in ms between each connection attempt if not connected
reconnAttemptInterval = 5000
# Time in seconds to wait when not connected to a wifi network AND mqtt server before opening it's AP and webREPL.
# The "emergencyMode" function is executed after the timeout
emergencyModeTimeout = 15
lightstate, switchstate = 0, 0
downtimeCounter = 0
mqttActive = False
emergencyMode = False
MainLoop = True
returnCode = 0
compareTime = 0
# Proper shutdown procedure
def resetProcedure(code):
# We need to disable all possible interrupts because we are writing data to the FS
# If an interrupt happens during file write, our entire FS will get corrupted.
global MainLoop
cm.connMQTT(mqtt, False)
triac.activate(0)
MainLoop = False
boot.saveSession(code, lightstate, switchstate)
machine.reset()
# this is what gets executed when a message gets received
def sub_cb(topic, msg):
global lightstate
sendFeedback = False
print((topic, msg))
if not(isinstance(msg, str)): # Checks if incomming message is a string
msg = msg.decode("utf-8") # if not turn it into a string
if(msg == "ON"):
sendFeedback = True
lightstate = 1
triac.activate(lightstate)
elif(msg == "OFF"):
sendFeedback = True
lightstate = 0
triac.activate(lightstate)
elif(msg == "TOGGLE"):
sendFeedback = True
lightstate = 1 - lightstate
triac.activate(lightstate)
elif(msg == "REPORT"):
mqtt.publish("light", lightstate, False, 1)
sendFeedback = True
elif(msg == "RESTART"):
resetProcedure(1)
elif(msg == "EDIT"):
resetProcedure(0)
if cm.mqttActive and sendFeedback: # Sends every change actively to the serv
mqtt.publish("light", str(lightstate), False, 1)
mqtt = cm.setMQTT(sub_cb)
def attemptConnect():
global downtimeCounter
if cm.wlan.isconnected() and not cm.mqttActive:
print("Attempting to connect MQTT")
if cm.connMQTT(mqtt, True):
downtimeCounter = 0
emergencyReact(False)
if not cm.wlan.isconnected() or not cm.mqttActive:
downtimeCounter += 1
if downtimeCounter >= (emergencyModeTimeout * 1000) / reconnAttemptInterval:
emergencyReact(True)
def emergencyReact(state):
global emergencyMode
if state and not emergencyMode:
emergencyMode = True
cm.setAP(True)
if "webREPL" not in sys.modules:
import webrepl
webrepl.start()
elif not state and emergencyMode:
emergencyMode = False
cm.setAP(False)
webrepl.stop()
# Checks the physical input pin and toggles the light if the pin state changed from last time when this fn was called.
# 0 - Sends MQTT messaged when the switch changes stage. Uses short pulses for triac activation (via interrupts).
# 1 - Does not send MQTT messages. Uses constant on or off value on the gate pin. (Useful for not corrupting files)
def checkInputChange(mode):
global switchstate
global lightstate
if(switchPin.value() != switchstate):
switchstate = switchPin.value()
if mode == 0:
sub_cb("light", "TOGGLE")
return 1
elif mode == 1:
lightstate = 1 - lightstate
triac.outPin.value(bool(lightstate)) # Inverts out pin value
else:
return 0
def main():
# Executed on boot
global switchPin
global switchstate
global lightstate
switchPin = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)
cm.setAP(False) # We don't want AP in work mode by default
savedData = boot.readSession()
lightstate = int(savedData[1])
switchstate = int(savedData[2])
triac.activate(lightstate)
print("Bulb reinitialised")
attemptConnect()
# Main program
while(MainLoop):
global compareTime
time.sleep_ms(checkFrequency)
if time.ticks_diff(time.ticks_ms(), compareTime) > reconnAttemptInterval:
attemptConnect()
print("Done MQTT connect")
compareTime = time.ticks_ms()
if not emergencyMode:
checkInputChange(0)
if cm.mqttActive:
mqtt.check_msg()
else:
checkInputChange(1)