From aa146b15e5094b43c9675a0f8e16980423ce9316 Mon Sep 17 00:00:00 2001 From: Thomas Klaehn Date: Thu, 30 Mar 2017 11:58:55 +0200 Subject: [PATCH] gate: reorder - stage 2 Signed-off-by: Thomas Klaehn --- source/{gate => }/close.py | 25 ++-- source/engine/__init__.py | 12 +- source/gate/__init__.py | 176 ++++++++++++++++++++++++++++ source/gate/gate_handler.py | 24 ---- source/gate/gate_state.py | 176 ---------------------------- source/gate/light.py | 18 --- source/gate_guard.py | 6 +- source/light.py | 18 +++ source/light_sensor/__init__.py | 11 ++ source/light_sensor/light_sensor.py | 11 -- source/{gate => }/open.py | 21 ++-- 11 files changed, 236 insertions(+), 262 deletions(-) rename source/{gate => }/close.py (54%) delete mode 100644 source/gate/gate_handler.py delete mode 100644 source/gate/gate_state.py delete mode 100644 source/gate/light.py create mode 100644 source/light.py delete mode 100644 source/light_sensor/light_sensor.py rename source/{gate => }/open.py (61%) diff --git a/source/gate/close.py b/source/close.py similarity index 54% rename from source/gate/close.py rename to source/close.py index d4050a6..c3371d8 100644 --- a/source/gate/close.py +++ b/source/close.py @@ -5,11 +5,10 @@ Created on Dec 23, 2016 ''' import sys import time -from datetime import datetime as dt -from data_buffer import DataBuffer -from gate.gate_handler import GateHandler -from power_sensor import PowerSensor +import data_buffer +import engine +import power_sensor POWER_SENSOR_I2C_BUS = 1 POWER_SENSOR_I2C_ADDRESS = 0x40 @@ -19,24 +18,24 @@ CONSECUTIVE_POWER_READS = 1000 MAX_ENGINE_POWER = {"up":330, "down":280} def main(argv): - gate_handler = GateHandler() - power_sensor = PowerSensor(POWER_SENSOR_I2C_BUS, POWER_SENSOR_I2C_ADDRESS) - power_data = DataBuffer(CONSECUTIVE_POWER_READS) - gate_handler.close() + __engine = engine.Engine(gpio_1=13, gpio_2=19) + __power_sensor = power_sensor.PowerSensor(POWER_SENSOR_I2C_BUS, POWER_SENSOR_I2C_ADDRESS) + __power_data = data_buffer.DataBuffer(CONSECUTIVE_POWER_READS) + __engine.down() try: while True: - rd = power_sensor.power_mw() - power_data.push(rd) - average = power_data.average() + rd = __power_sensor.power_mw() + __power_data.push(rd) + average = __power_data.average() print str(time.time()) + " " + str(rd) if average != None: if average > MAX_ENGINE_POWER["down"]: - gate_handler.stop() + __engine.stop() # print "Gate successfully closed" return 0 except KeyboardInterrupt: - gate_handler.stop() + __engine.stop() # print "Closing procedure interrupted." return 1 diff --git a/source/engine/__init__.py b/source/engine/__init__.py index eeb5793..47f3b0d 100644 --- a/source/engine/__init__.py +++ b/source/engine/__init__.py @@ -1,14 +1,14 @@ -from gpio import Gpio +import gpio -class Engine: +class Engine(object): def __init__(self, gpio_1 = 13, gpio_2 = 19): - self.gpio_1 = Gpio(gpio_1) - self.gpio_2 = Gpio(gpio_2) + self.gpio_1 = gpio.Gpio(gpio_1) + self.gpio_2 = gpio.Gpio(gpio_2) self.gpio_1.export() - self.gpio_1.direction(Gpio.DIRECTION_OUT) + self.gpio_1.direction(gpio.Gpio.DIRECTION_OUT) self.gpio_2.export() - self.gpio_2.direction(Gpio.DIRECTION_OUT) + self.gpio_2.direction(gpio.Gpio.DIRECTION_OUT) self.stop() def stop(self): diff --git a/source/gate/__init__.py b/source/gate/__init__.py index e69de29..6494499 100644 --- a/source/gate/__init__.py +++ b/source/gate/__init__.py @@ -0,0 +1,176 @@ +''' +Created on Dec 19, 2016 + +@author: klaehn +''' +from time import time, sleep +import mqtt +import data_buffer +import light_sensor +import engine +from power_sensor import PowerSensor + +STATE_INIT = "init" +STATE_OPENED = "open" +STATE_CLOSED = "close" +STATE_OPENING = "opening" +STATE_CLOSING = "closing" +STATE_ERROR = "error" + +LIGHT_READ_DELAY_S = 30 +LIGHT_CONSECUTIVE_READS = 10 +LIGHT_LX_THRESHOLD = {"open":10, "close":5} + +MQTT_HOST = "proxy" +MQTT_TOPIC = "outdoor/chickenhouse/newgate" + +LIGHT_SENSOR_I2C_BUS = 1 +LIGHT_SENSOR_I2C_ADDRESS = 0x23 + +POWER_SENSOR_I2C_BUS = 1 +POWER_SENSOR_I2C_ADDRESS = 0x40 +POWER_CONSECUTIVE_READS = 1000 + +MAX_ENGINE_POWER = {"up":330, "down":280} +MAX_GATE_RUNTIME = {"open":300, "close":300} +MIN_GATE_RUNTIME = {"open":10, "close":10} + + +class Gate(object): + def __init__(self): + self.__state_handler = {STATE_INIT:self.__init_handler, \ + STATE_OPENED:self.__opened_handler, \ + STATE_CLOSED:self.__closed_handler, \ + STATE_OPENING:self.__opening_handler, \ + STATE_CLOSING:self.__closing_handler, \ + STATE_ERROR:self.__error_handler} + self.__next_state = "init" + self.__last_state = "error" + + self.__light_sensor = light_sensor.LightSensor(LIGHT_SENSOR_I2C_BUS, \ + LIGHT_SENSOR_I2C_ADDRESS) + self.__light_data = data_buffer.DataBuffer(LIGHT_CONSECUTIVE_READS) + self.__comserver = mqtt.Mqtt(MQTT_HOST) + self.__engine = engine.Engine(gpio_1=13, gpio_2=19) + self.__power_sensor = PowerSensor(POWER_SENSOR_I2C_BUS, \ + POWER_SENSOR_I2C_ADDRESS) + self.__power_data = data_buffer.DataBuffer(POWER_CONSECUTIVE_READS) + self.__gate_move_timeout = 0 + self.__light_read_timeout = 0 + self.__error_count = 0 + self.__runtime_open = 0 + self.__runtime_close = 0 + + def poll(self): + current_time = time() + if current_time >= self.__light_read_timeout: + self.__light_read_timeout = current_time + LIGHT_READ_DELAY_S + self.__light_data.push(self.__light_sensor.read()) + self.__state_handler[self.__next_state](self.__light_data.average()) + + def __update_state(self, new_state): + self.__last_state = self.__next_state + self.__next_state = new_state + + + def __is_transition(self): + if self.__last_state != self.__next_state: + return True + return False + + + def __init_handler(self, light_avg): + ''' + In init we don't know anything neither about gate state nor about + light. So first we try to reach STATE_CLOSED. + ''' + #pylint: disable=unused-argument + self.__comserver.connect() + self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ + " gate gard initiated") + self.__comserver.disconnect() + self.__update_state(STATE_OPENING) + + + def __opened_handler(self, light_avg): + next_state = self.__next_state + if self.__is_transition(): + self.__engine.down() + sleep(5) + self.__engine.stop() + self.__comserver.transmit(MQTT_TOPIC, str(time()) + " Opened " + \ + str(self.__power_data.average()) + " mW") + self.__power_data.clear() + + if light_avg <= LIGHT_LX_THRESHOLD["close"]: + next_state = STATE_CLOSING + + self.__update_state(next_state) + + + def __closed_handler(self, light_avg): + next_state = self.__next_state + if self.__is_transition(): + self.__engine.up() + sleep(5) + self.__engine.stop() + self.__comserver.transmit(MQTT_TOPIC, str(time()) + " Closed " + \ + str(self.__power_data.average()) + " mW") + self.__power_data.clear() + + if light_avg > LIGHT_LX_THRESHOLD["open"]: + next_state = STATE_OPENING + + self.__update_state(next_state) + + + def __opening_handler(self, light_avg): + next_state = self.__next_state + if self.__is_transition(): + self.__runtime_open = time() + MIN_GATE_RUNTIME["open"] + self.__engine.up() + self.__gate_move_timeout = time() + MAX_GATE_RUNTIME["open"] + self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ + " Opening " + str(light_avg) + " lx") + + if time() > self.__gate_move_timeout: + next_state = STATE_ERROR + else: + self.__power_data.push(self.__power_sensor.power_mw()) + current_avg = self.__power_data.average() + if current_avg != None: + if current_avg > MAX_ENGINE_POWER["up"]: + if time() > self.__runtime_open: + next_state = STATE_OPENED + + self.__update_state(next_state) + + def __closing_handler(self, light_avg): + next_state = self.__next_state + if self.__is_transition(): + self.__runtime_close = time() + MIN_GATE_RUNTIME["close"] + self.__engine.down() + self.__gate_move_timeout = time() + MAX_GATE_RUNTIME["close"] + self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ + " Closing " + str(light_avg) + " lx") + + if time() > self.__gate_move_timeout: + next_state = STATE_ERROR + else: + self.__power_data.push(self.__power_sensor.power_mw()) + current_avg = self.__power_data.average() + if current_avg != None: + if current_avg > MAX_ENGINE_POWER["down"]: + if time() > self.__runtime_close: + next_state = STATE_CLOSED + + self.__update_state(next_state) + + + def __error_handler(self, light_avg): + #pylint: disable=unused-argument + if self.__is_transition(): + self.__engine.stop() + self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ + " Error handler!!!") + self.__update_state(STATE_INIT) diff --git a/source/gate/gate_handler.py b/source/gate/gate_handler.py deleted file mode 100644 index 137e63a..0000000 --- a/source/gate/gate_handler.py +++ /dev/null @@ -1,24 +0,0 @@ -''' -Created on Dec 19, 2016 - -@author: klaehn -''' - -from engine import Engine - -class GateHandler(object): - """Gate handler class""" - def __init__(self): - self.__engine = Engine(13, 19) - - def open(self): - """Open the gate""" - self.__engine.up() - - def close(self): - """Close the gate""" - self.__engine.down() - - def stop(self): - """Stop the Engine""" - self.__engine.stop() diff --git a/source/gate/gate_state.py b/source/gate/gate_state.py deleted file mode 100644 index e0aba39..0000000 --- a/source/gate/gate_state.py +++ /dev/null @@ -1,176 +0,0 @@ -''' -Created on Dec 19, 2016 - -@author: klaehn -''' -from time import time, sleep -from communiate import Mqtt -from data_buffer import DataBuffer -from light_sensor.light_sensor import light_sensor -from gate.gate_handler import GateHandler -from power_sensor import PowerSensor - -STATE_INIT = "init" -STATE_OPENED = "open" -STATE_CLOSED = "close" -STATE_OPENING = "opening" -STATE_CLOSING = "closing" -STATE_ERROR = "error" - -LIGHT_READ_DELAY_S = 30 -LIGHT_CONSECUTIVE_READS = 10 -LIGHT_LX_THRESHOLD = {"open":10, "close":5} - -MQTT_HOST = "proxy" -MQTT_TOPIC = "outdoor/chickenhouse/gate" - -LIGHT_SENSOR_I2C_BUS = 1 -LIGHT_SENSOR_I2C_ADDRESS = 0x23 - -POWER_SENSOR_I2C_BUS = 1 -POWER_SENSOR_I2C_ADDRESS = 0x40 -POWER_CONSECUTIVE_READS = 1000 - -MAX_ENGINE_POWER = {"up":330, "down":280} -MAX_GATE_RUNTIME = {"open":300, "close":300} -MIN_GATE_RUNTIME = {"open":10, "close":10} - - -class GateState(object): - def __init__(self): - self.__state_handler = {STATE_INIT:self.__init_handler, \ - STATE_OPENED:self.__opened_handler, \ - STATE_CLOSED:self.__closed_handler, \ - STATE_OPENING:self.__opening_handler, \ - STATE_CLOSING:self.__closing_handler, \ - STATE_ERROR:self.__error_handler} - self.__next_state = "init" - self.__last_state = "error" - - self.__light_sensor = light_sensor(LIGHT_SENSOR_I2C_BUS, \ - LIGHT_SENSOR_I2C_ADDRESS) - self.__light_data = DataBuffer(LIGHT_CONSECUTIVE_READS) - self.__comserver = Mqtt(MQTT_HOST) - self.__gate_handler = GateHandler() - self.__power_sensor = PowerSensor(POWER_SENSOR_I2C_BUS, \ - POWER_SENSOR_I2C_ADDRESS) - self.__power_data = DataBuffer(POWER_CONSECUTIVE_READS) - self.__gate_move_timeout = 0 - self.__light_read_timeout = 0 - self.__error_count = 0 - self.__runtime_open = 0 - self.__runtime_close = 0 - - def poll(self): - current_time = time() - if current_time >= self.__light_read_timeout: - self.__light_read_timeout = current_time + LIGHT_READ_DELAY_S - self.__light_data.push(self.__light_sensor.read()) - self.__state_handler[self.__next_state](self.__light_data.average()) - - def __update_state(self, new_state): - self.__last_state = self.__next_state - self.__next_state = new_state - - - def __is_transition(self): - if self.__last_state != self.__next_state: - return True - return False - - - def __init_handler(self, light_avg): - ''' - In init we don't know anything neither about gate state nor about - light. So first we try to reach STATE_CLOSED. - ''' - #pylint: disable=unused-argument - self.__comserver.connect() - self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ - " gate gard initiated") - self.__comserver.disconnect() - self.__update_state(STATE_OPENING) - - - def __opened_handler(self, light_avg): - next_state = self.__next_state - if self.__is_transition(): - self.__gate_handler.close() - sleep(5) - self.__gate_handler.stop() - self.__comserver.transmit(MQTT_TOPIC, str(time()) + " Opened " + \ - str(self.__power_data.average()) + " mW") - self.__power_data.clear() - - if light_avg <= LIGHT_LX_THRESHOLD["close"]: - next_state = STATE_CLOSING - - self.__update_state(next_state) - - - def __closed_handler(self, light_avg): - next_state = self.__next_state - if self.__is_transition(): - self.__gate_handler.open() - sleep(5) - self.__gate_handler.stop() - self.__comserver.transmit(MQTT_TOPIC, str(time()) + " Closed " + \ - str(self.__power_data.average()) + " mW") - self.__power_data.clear() - - if light_avg > LIGHT_LX_THRESHOLD["open"]: - next_state = STATE_OPENING - - self.__update_state(next_state) - - - def __opening_handler(self, light_avg): - next_state = self.__next_state - if self.__is_transition(): - self.__runtime_open = time() + MIN_GATE_RUNTIME["open"] - self.__gate_handler.open() - self.__gate_move_timeout = time() + MAX_GATE_RUNTIME["open"] - self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ - " Opening " + str(light_avg) + " lx") - - if time() > self.__gate_move_timeout: - next_state = STATE_ERROR - else: - self.__power_data.push(self.__power_sensor.power_mw()) - current_avg = self.__power_data.average() - if current_avg != None: - if current_avg > MAX_ENGINE_POWER["up"]: - if time() > self.__runtime_open: - next_state = STATE_OPENED - - self.__update_state(next_state) - - def __closing_handler(self, light_avg): - next_state = self.__next_state - if self.__is_transition(): - self.__runtime_close = time() + MIN_GATE_RUNTIME["close"] - self.__gate_handler.close() - self.__gate_move_timeout = time() + MAX_GATE_RUNTIME["close"] - self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ - " Closing " + str(light_avg) + " lx") - - if time() > self.__gate_move_timeout: - next_state = STATE_ERROR - else: - self.__power_data.push(self.__power_sensor.power_mw()) - current_avg = self.__power_data.average() - if current_avg != None: - if current_avg > MAX_ENGINE_POWER["down"]: - if time() > self.__runtime_close: - next_state = STATE_CLOSED - - self.__update_state(next_state) - - - def __error_handler(self, light_avg): - #pylint: disable=unused-argument - if self.__is_transition(): - self.__gate_handler.stop() - self.__comserver.transmit(MQTT_TOPIC, str(time()) + \ - " Error handler!!!") - self.__update_state(STATE_INIT) diff --git a/source/gate/light.py b/source/gate/light.py deleted file mode 100644 index 779b5cb..0000000 --- a/source/gate/light.py +++ /dev/null @@ -1,18 +0,0 @@ -''' -Created on Dec 24, 2016 - -@author: tkl -''' -import sys -import time -from light_sensor.light_sensor import light_sensor -import mqtt - -def main(): - conn = mqtt.Mqtt(hostname='proxy') - light = light_sensor(1, 0x23) - conn.transmit("outdoor/chickenhouse/sensors/light", str(int(time.time())) + " " + \ - str(light.read()) + " lx") - -if __name__ == "__main__": - sys.exit(main()) diff --git a/source/gate_guard.py b/source/gate_guard.py index 2e217d5..fc80f87 100644 --- a/source/gate_guard.py +++ b/source/gate_guard.py @@ -5,14 +5,14 @@ Created on Dec 19, 2016 ''' import sys import time -from gate.gate_state import GateState +import gate def main(): - gate_state = GateState() + gate_state = gate.Gate() try: while True: gate_state.poll() - time.sleep(0.001) + time.sleep(0.1) except KeyboardInterrupt: print "key exit" diff --git a/source/light.py b/source/light.py new file mode 100644 index 0000000..9f5f573 --- /dev/null +++ b/source/light.py @@ -0,0 +1,18 @@ +''' +Created on Dec 24, 2016 + +@author: tkl +''' +import sys +import time +import light_sensor +import mqtt + +def main(): + conn = mqtt.Mqtt(hostname='proxy') + light = light_sensor.LightSensor(1, 0x23) + conn.transmit("outdoor/chickenhouse/sensors/light", \ + str(int(time.time())) + " " + str(light.read())) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/source/light_sensor/__init__.py b/source/light_sensor/__init__.py index e69de29..c59d164 100644 --- a/source/light_sensor/__init__.py +++ b/source/light_sensor/__init__.py @@ -0,0 +1,11 @@ +import smbus + +class LightSensor(object): + def __init__(self, bus = 1, addr = 0x23): + self.__i2c_device = bus + self.__i2c_addr = addr + self.__i2c_device = smbus.SMBus(self.__i2c_device) + + def read(self): + data = self.__i2c_device.read_i2c_block_data(self.__i2c_addr, 0x10) + return int(round((data[0] * 256 + data[1]) / 1.2, 0)) diff --git a/source/light_sensor/light_sensor.py b/source/light_sensor/light_sensor.py deleted file mode 100644 index 07b8a66..0000000 --- a/source/light_sensor/light_sensor.py +++ /dev/null @@ -1,11 +0,0 @@ -import smbus - -class light_sensor: - def __init__(self, bus = 1, addr = 0x23): - self.__i2c_device = bus - self.__i2c_addr = addr - self.__i2c_device = smbus.SMBus(self.__i2c_device) - - def read(self): - data = self.__i2c_device.read_i2c_block_data(self.__i2c_addr, 0x10) - return int(round((data[0] * 256 + data[1]) / 1.2, 0)) diff --git a/source/gate/open.py b/source/open.py similarity index 61% rename from source/gate/open.py rename to source/open.py index a6a6c6a..e1db68e 100644 --- a/source/gate/open.py +++ b/source/open.py @@ -5,11 +5,10 @@ Created on Dec 23, 2016 ''' import sys import time -from datetime import datetime as dt -from data_buffer import DataBuffer -from gate.gate_handler import GateHandler -from power_sensor import PowerSensor +import data_buffer +import engine +import power_sensor POWER_SENSOR_I2C_BUS = 1 POWER_SENSOR_I2C_ADDRESS = 0x40 @@ -19,24 +18,24 @@ CONSECUTIVE_POWER_READS = 1000 MAX_ENGINE_POWER = {"up":330, "down":290} def main(argv): - gate_handler = GateHandler() - power_sensor = PowerSensor(POWER_SENSOR_I2C_BUS, POWER_SENSOR_I2C_ADDRESS) - power_data = DataBuffer(CONSECUTIVE_POWER_READS) - gate_handler.open() + __engine = engine.Engine(gpio_1=13, gpio_2=19) + __power_sensor = power_sensor.PowerSensor(POWER_SENSOR_I2C_BUS, POWER_SENSOR_I2C_ADDRESS) + power_data = data_buffer.DataBuffer(CONSECUTIVE_POWER_READS) + __engine.up() try: while True: - rd = power_sensor.power_mw() + rd = __power_sensor.power_mw() power_data.push(rd) average = power_data.average() print str(time.time()) + " " + str(rd) if average != None: if average > MAX_ENGINE_POWER["up"]: - gate_handler.stop() + __engine.stop() # print "Gate successfully opened" return 0 except KeyboardInterrupt: - gate_handler.stop() + __engine.stop() print "Closing procedure interrupted." return 1