Skip to content

Commit

Permalink
Improved Device managing (#26)
Browse files Browse the repository at this point in the history
* fix(mqtt)

* feat(drivers)

* feat(updates)

* feat(relesae setup)
  • Loading branch information
psp515 authored May 6, 2024
1 parent 660507f commit c09c459
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 86 deletions.
48 changes: 37 additions & 11 deletions src/configuration/devices.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"data":
{
"loopSpanMs": 500,
"pin": 1,
"pin": 16,
"temperature":
{
"unit": "Celsius",
Expand All @@ -22,7 +22,7 @@
"threshold":{
"type": "value",
"value": 0.2,
"minimalIntervalSeconds": 20
"minimalIntervalSeconds": 4
}
},
"humidity":
Expand All @@ -33,12 +33,11 @@
"threshold":{
"type": "value",
"value": 1,
"minimalIntervalSeconds": 20
"minimalIntervalSeconds": 4
}
}
}
},

{
"id": "2",
"type": "soil",
Expand All @@ -61,15 +60,42 @@
"sendAsJson": true,
"threshold":{
"type": "value",
"value": 1,
"minimalIntervalSeconds": 20
"value": 5,
"minimalIntervalSeconds": 5
}
}
}
},

{
"id": "3",
"type": "soil",
"name": "gravity_v1",
"ground": 38,
"vcc": 36,
"availability": {
"enabled": true,
"topic": "availability"
},
"data":
{
"loopSpanMs": 500,
"mux_id": 1,
"channel": 15,
"moisture":
{
"unit": "Percentage",
"topic": "moisture",
"sendAsJson": true,
"threshold":{
"type": "value",
"value": 1,
"minimalIntervalSeconds": 5
}
}
}
},
{
"id": "4",
"type": "light",
"name": "is",
"ground": 38,
Expand All @@ -81,19 +107,19 @@
"data":
{
"loopSpanMs": 500,
"mux_id": 1,
"channel": 2,
"adcPin": 27,
"insolation":
{
"unit": "Percentage",
"topic": "insolation",
"sendAsJson": true,
"threshold":{
"type": "value",
"value": 1,
"minimalIntervalSeconds": 20
"value": 4,
"minimalIntervalSeconds": 5
}
}
}
}
]

22 changes: 0 additions & 22 deletions src/drivers/insolation.py

This file was deleted.

20 changes: 0 additions & 20 deletions src/drivers/sms.py

This file was deleted.

8 changes: 2 additions & 6 deletions src/features/devices/device_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def _create_item(self, config):
raise NotImplementedError("Air device is not supported")

if config.type == "soil":
if config.name == "sms":
if config.name == "sms" or config.name == "gravity_v1":

mux_id = config.config["mux_id"]
accessor = self.find_analog_accessor(mux_id)
Expand All @@ -35,11 +35,7 @@ def _create_item(self, config):

if config.type == "light":
if config.name == "is":

mux_id = int(config.config["mux_id"])
accessor = self.find_analog_accessor(mux_id)

return InsolationSensor(self.client, config, self.logger, accessor)
return InsolationSensor(self.client, config, self.logger)

raise NotImplementedError(f"Device {config.type}-{config.name} is not supported")

Expand Down
27 changes: 27 additions & 0 deletions src/features/devices/drivers/adc_driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from features.analog_accessor.analog_accessor import AnalogAccessor


class AnalogDriver:
def __init__(self, analog_accessor: AnalogAccessor, channel: int):
self.analog_accessor = analog_accessor
self.channel = channel
self.min = 0
self.max = 65535

async def read_raw(self):
return await self.analog_accessor.read(self.channel)

async def read(self):
return await self._read()

async def _read(self):
raw = await self.read_raw()

if raw <= self.min:
return 0
if raw >= self.max:
return 100

calc = int(raw / self.max * 100)

return min(100, max(0, calc))
27 changes: 27 additions & 0 deletions src/features/devices/light/drivers/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from features.devices.drivers.adc_driver import AnalogDriver
from math import log, e
from machine import Pin, ADC
from uasyncio import sleep_ms


class InsolationDriver(AnalogDriver):
def __init__(self, adc_pin: int):
self.adc = ADC(Pin(adc_pin))
self.light = 1000
self.dark = 50000

async def read_raw(self):
await sleep_ms(1)
return self.adc.read_u16()

async def _read(self):
raw = await self.read_raw()

if raw >= self.dark:
return 0
if raw <= self.light:
return 100

calc = int(276.295 - 24.188 * log(raw, e))

return min(100, max(0, calc))
21 changes: 7 additions & 14 deletions src/features/devices/light/insolation_sensor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from features.devices.device import Device, DeviceConfig, ADCTopic
from features.logger.logger import Logger
from features.mqtt.mqtt import BaseMqttClient
from utime import ticks_ms, ticks_diff, time
from ujson import dumps, loads
from utime import ticks_ms
from features.analog_accessor.analog_accessor import AnalogAccessor
import machine
from drivers.insolation import InsolationDriver

from features.devices.light.drivers.default import InsolationDriver
import uasyncio


Expand All @@ -16,29 +15,23 @@ class Insolation(ADCTopic):
class InsolationSensor(Device):
def __init__(self, mqtt: BaseMqttClient,
config: DeviceConfig,
logger: Logger,
analog_accessor: AnalogAccessor):
logger: Logger):
super().__init__(mqtt, config, logger)
data = config.config

self._insolation = Insolation(mqtt, data["insolation"], logger)
self.loop_span_ms = data["loopSpanMs"]
channel = data["channel"]
pin = data["adcPin"]

self.sensor = InsolationDriver(analog_accessor, channel)
self.sensor = InsolationDriver(pin)

async def _update_config(self):
pass

async def _loop(self):
current_time = ticks_ms()
await self.sensor.measure()
insolation = await self.sensor.read()

insolation = 100 - self.sensor.insolation()
self._insolation.update(self.base_topic, current_time, insolation)

self.logger.debug(f"Insolation: {insolation}.")

await uasyncio.sleep_ms(self.loop_span_ms)


23 changes: 23 additions & 0 deletions src/features/devices/soil_humidity/drivers/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from features.analog_accessor.analog_accessor import AnalogAccessor
from features.devices.drivers.adc_driver import AnalogDriver
from math import log, e


class SMSDriver(AnalogDriver):
def __init__(self, analog_accessor: AnalogAccessor, channel: int):
super().__init__(analog_accessor, channel)
self.wet = 26000
self.mid = 33000
self.dry = 63000

async def _read(self):
raw = await self.read_raw()

if raw >= self.dry:
return 0
if raw <= self.wet:
return 100

calc = int(1162.08 - 105.507 * log(raw, e))

return min(100, max(0, calc))
23 changes: 23 additions & 0 deletions src/features/devices/soil_humidity/drivers/gravity_v1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from features.analog_accessor.analog_accessor import AnalogAccessor
from features.devices.drivers.adc_driver import AnalogDriver
from math import log, e


class GravityV1(AnalogDriver):
def __init__(self, analog_accessor: AnalogAccessor, channel: int):
super().__init__(analog_accessor, channel)
self.wet = 23000
self.mid = 37000
self.dry = 50000

async def _read(self):
raw = await self.read_raw()

if raw >= self.dry:
return 0
if raw <= self.wet:
return 100

calc = int(1246.17 - 115.51 * log(raw, e))

return min(100, max(0, calc))
18 changes: 9 additions & 9 deletions src/features/devices/soil_humidity/soil_moisture_sensor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from features.devices.device import Device, DeviceConfig, ADCTopic
from features.logger.logger import Logger
from features.mqtt.mqtt import BaseMqttClient
from utime import ticks_ms, ticks_diff, time
from ujson import dumps, loads
from features.analog_accessor.analog_accessor import AnalogAccessor
import machine
from drivers.sms import SMSDriver
from features.devices.soil_humidity.drivers.default import SMSDriver
from features.devices.soil_humidity.drivers.gravity_v1 import GravityV1
from utime import ticks_ms
import uasyncio


Expand All @@ -23,19 +22,20 @@ def __init__(self, mqtt: BaseMqttClient,

self._moisture = Moisture(mqtt, data["moisture"], logger)
self.loop_span_ms = data["loopSpanMs"]
channel = data["channel"]
self.sensor = SMSDriver(analog_accessor, channel)
self.sensor = self._create_sensor(analog_accessor, data["channel"])

def _create_sensor(self, analog_accessor: AnalogAccessor, channel: int):
if self.config.name == "gravity_v1":
return GravityV1(analog_accessor, channel)

return SMSDriver(analog_accessor, channel)

async def _update_config(self):
pass

async def _loop(self):
current_time = ticks_ms()
await self.sensor.measure()

moisture = self.sensor.moisture()
moisture = await self.sensor.read()

self._moisture.update(self.base_topic, current_time, moisture)
self.logger.debug(f"Moisture: {moisture}.")
Expand Down
1 change: 0 additions & 1 deletion src/features/mqtt/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ def __init__(self, json: {}):
self.client = json.get("client")
self.ssl = json.get("ssl", True)
self.keep_alive = self.value_in_range(name="keepAlive", min_v=10, max_v=120)
self.refresh_rate_ms = self.value_in_range(name="refreshRateMs", min_v=100, max_v=10000)


class BaseMqttClient:
Expand Down
6 changes: 3 additions & 3 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from features.analog_accessor.analog_accessor_factory import AnalogAccessorFactory
from features.devices.device_factory import DeviceFactory
from features.logger.file_logger import FileLogger
from features.logger.logger_levels import LoggerLevels
from features.logger.logger import Logger
from features.mqtt.mqtt_factory import MqttFactory
from features.network.connection_factory import ConnectionFactory

Expand All @@ -17,9 +17,9 @@

def setup_fail(logger: Logger, message: str, error_code: int):
logger.error(message)
logger.error(str(error_code))
sleep(5)
sys.exit(error_code)
# in release change to reset()
reset()


if __name__ == '__main__':
Expand Down

0 comments on commit c09c459

Please sign in to comment.