Skip to content

Support for Linux Boards #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 59 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
7d61814
Arduino sensor bug fix
olixr Oct 29, 2020
719322c
Blinka Introduction in sensors/linux : sensor.py and humidity_sensor.py
SecT0uch Nov 5, 2020
d35b25a
Edit requirements.txt to match blinka changes
SecT0uch Nov 5, 2020
ce80e9b
Added linux worker.py and sendor_worker to load the linux sensors lib
SecT0uch Nov 5, 2020
ac7b486
PEP8 related changes (TAB to 4 spaces, etc..)
SecT0uch Nov 5, 2020
d749ac3
WIP - Adapted mudpi.py - Fixes
SecT0uch Nov 5, 2020
0ab4de6
WIP - Fix temperatue and humidity reading
SecT0uch Nov 5, 2020
2af7b16
PEP8 changes to float_sensor.py
SecT0uch Nov 5, 2020
8842b42
Blinka introduction in float_sensor.py
SecT0uch Nov 5, 2020
c5895e8
PEP8 changes to i2c/*
SecT0uch Nov 5, 2020
1eb53dc
PEP8 changes to i2c_worker.py
SecT0uch Nov 5, 2020
d195d88
Uncommented linux.i2c import
SecT0uch Nov 5, 2020
58fd4fa
PEP8 changes in linux/i2c/sensor.py
SecT0uch Nov 5, 2020
8522918
More PEP8 changes
SecT0uch Nov 5, 2020
a63e303
Removed RPi dependency and commented readPin(). Not used ?
SecT0uch Nov 5, 2020
e051484
Changed import pi.i2c to linux.i2c
SecT0uch Nov 5, 2020
8bc96c7
PEP8 changes in relay_worker.py
SecT0uch Nov 5, 2020
4eac422
Now manage relays with digitalio
SecT0uch Nov 6, 2020
b319191
Uncomment linux.relay_worker
SecT0uch Nov 6, 2020
19005bd
Apply some linting to the code.
yeyeto2788 Nov 6, 2020
b5f2b32
Try refactoring to a base sensor to avoid code duplication.
yeyeto2788 Nov 6, 2020
f5971e8
Add also the mcp3xxx module on the refactor
yeyeto2788 Nov 6, 2020
bd92c67
Merge remote-tracking branch 'origin/BlinkaMigration'
yeyeto2788 Nov 6, 2020
c647efe
Merge master with blinka migration
yeyeto2788 Nov 6, 2020
096ea8c
Merge pull request #1 from yeyeto2788/master
SecT0uch Nov 6, 2020
ccba1e9
Removed sensors/pi/* (Now replaced by sensors/linux)
SecT0uch Nov 6, 2020
579d907
Extra PEP8 on control_worker.py
SecT0uch Nov 6, 2020
3ca5139
PEP8 on control.py
SecT0uch Nov 6, 2020
3046731
PEP8 on switch_control.py and button.contol.py
SecT0uch Nov 6, 2020
7ab32a7
Change pi import to linux in control_worker.py
SecT0uch Nov 6, 2020
bf6159a
Extra PEP8
SecT0uch Nov 6, 2020
c663453
WIP on control.py
SecT0uch Nov 6, 2020
6694dbc
Fix : convert pin str to pin_obj
SecT0uch Nov 7, 2020
40a9ecc
Fix: exit the device after successfful reading
SecT0uch Nov 7, 2020
293ee32
Typo: Missing \t
SecT0uch Nov 7, 2020
2d8c926
Code cleanup
SecT0uch Nov 7, 2020
086f7d7
Introduction of the t9602 i2csensor
SecT0uch Nov 7, 2020
4fba722
Rounding values + comments
SecT0uch Nov 7, 2020
b187d22
PEP8, typos and comment on camera_worker
SecT0uch Nov 9, 2020
ab9ffb9
PEP8 changes on lcd_worker
SecT0uch Nov 9, 2020
db581cf
Uncomment lcd, camera, trigger and sequence workers
SecT0uch Nov 9, 2020
8904608
Removed workers/pi as it as been moved and adapted to linux.
SecT0uch Nov 9, 2020
495a0d8
Fix: Point to the right module
SecT0uch Nov 9, 2020
36e7f6b
PEP8: TAB to spaces
SecT0uch Nov 9, 2020
49e9489
Adapted configuration
SecT0uch Nov 9, 2020
0810a3a
Update dependencies
SecT0uch Nov 9, 2020
4d243ce
Updated README : T9602 sensor, 8 channel relay module and compatible …
SecT0uch Nov 9, 2020
3a6b7e8
Typo
SecT0uch Nov 9, 2020
0f27e7a
Apply linting on code.
yeyeto2788 Nov 9, 2020
5009d61
Merge branch 'BlinkaMigration'
yeyeto2788 Nov 9, 2020
d94f374
Finished to port control to Blinka's digitalio
SecT0uch Nov 9, 2020
6a178d5
Uncomment control worker
SecT0uch Nov 9, 2020
e06a25c
Removed controls/pi, replaced by controls/linux
SecT0uch Nov 9, 2020
2cdfbb7
Move all common method to the utils module for convenience.
yeyeto2788 Nov 10, 2020
9bcda1e
Merge latest changes from @SecT0uch
yeyeto2788 Nov 10, 2020
73ef192
Rename variables.py into constants.py
yeyeto2788 Nov 10, 2020
64ed283
Merge pull request #3 from yeyeto2788/master
SecT0uch Nov 10, 2020
c171c75
Add check if pi before import camera_worker
SecT0uch Nov 11, 2020
755544f
Readability
SecT0uch Nov 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<p align="center"><img alt="MudPi Smart Garden" title="MudPi Smart Garden" src="https://mudpi.app/img/mudPI_LOGO_small_grad.png" width="200px"></p>

# MudPi Smart Garden
> A python library to gather sensor readings, trigger components, control solenoids and more in an event based system that can be run on a raspberry pi.
> A python library to gather sensor readings, trigger components, control solenoids and more in an event based system that can be run on a linux SBC, including Raspberry Pi.


## Documentation
Expand All @@ -17,7 +17,7 @@ For examples and guides on how to setup and use MudPi check out the [free guides


## Contributing
Any contributions you can make will be greatly appreciated. If you are interested in contributing please get in touch with me and submit a pull request. There is much more I would like to add support for, however being a single developer limits my scope. Therefore mainly bugs will be accepted as issues.
Any contributions you can make will be greatly appreciated. If you are interested in contributing please get in touch with me and submit a pull request. There is much more I would like to add support for, however being a single developer limits my scope. Therefore mainly bugs will be accepted as issues.


## Versioning
Expand All @@ -33,7 +33,7 @@ Breaking.Major.Minor
* [Twitter.com/MudpiApp](https://twitter.com/mudpiapp)

## Hardware Tested On
These are the devices and sensors I tested and used with MudPi successfully. Many sensors are similar so it will work with a range more than what is listed below.
These are the devices and sensors I tested and used with MudPi successfully. Many sensors are similar so it will work with a range more than what is listed below.

**Devices**
* [Raspberry Pi 2 Model B+](https://www.raspberrypi.org/products/raspberry-pi-2-model-b/)
Expand All @@ -53,13 +53,15 @@ These are the devices and sensors I tested and used with MudPi successfully. Man
* [DS18B20 Temperature Sensors](https://www.amazon.com/gp/product/B018KFX5X0/ref=oh_aui_detailpage_o08_s00?ie=UTF8&psc=1)
* [DHT11 Temperature/Humidity Sensor](https://www.amazon.com/gp/product/B01DKC2GQ0/ref=oh_aui_detailpage_o07_s05?ie=UTF8&psc=1)
* [DHT22 Temperature/Humidity Sensor](https://www.dfrobot.com/product-1102.html)
* [T9602 Temperature/Humidity Sensor](https://www.amphenol-sensors.com/en/telaire/humidity/527-humidity-sensors/3224-t9602)
* [Rain Sensor](https://www.amazon.com/gp/product/B01D9JK2F6/ref=oh_aui_detailpage_o03_s00?ie=UTF8&psc=1)
* [Ambient Light Sensor](https://www.dfrobot.com/product-1004.html)
* [DFROBOT Analog Capacitive Soil Moisture Sensor](https://www.amazon.com/gp/product/B01GHY0N4K/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1)
* [Soil Moisture Sensor](https://www.sparkfun.com/products/13322)

**Components**
* [4 Channel DC 5V Relay](https://www.amazon.com/gp/product/B00KTEN3TM/ref=oh_aui_detailpage_o08_s00?ie=UTF8&psc=1)
* [8 Channel DC 5V Relay](https://www.amazon.co.uk/SODIAL-Channel-Module-Arduino-Electronic/dp/B00IIDXYTA)
* [LCD 16 x 2 Display I2C](https://www.dfrobot.com/product-135.html)
* [LCD 16 x 2 Display I2C - PCF8574](https://www.amazon.com/Arducam-Display-Controller-Character-Backlight/dp/B019D9TYMI)
* [LCD 20 x 4 Display I2C](https://www.dfrobot.com/product-590.html)
Expand All @@ -74,4 +76,3 @@ This project is licensed under the BSD-4-Clause License - see the [LICENSE.md](L


<img alt="MudPi Smart Garden" title="MudPi Smart Garden" src="https://mudpi.app/img/mudPI_LOGO_small_flat.png" width="50px">

87 changes: 48 additions & 39 deletions action.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
import time
import json
import redis
import subprocess
import sys
sys.path.append('..')

import redis




class Action():

def __init__(self, config):
self.config = config
self.name = config.get("name", "Action")
self.type = config.get("type", "event")
self.key = config.get("key", None).replace(" ", "_").lower() if config.get("key") is not None else self.name.replace(" ", "_").lower()
# Actions will be either objects to publish for events or a command string to execute
self.action = config.get("action")
try:
self.r = config["redis"] if config["redis"] is not None else redis.Redis(host='127.0.0.1', port=6379)
except KeyError:
self.r = redis.Redis(host='127.0.0.1', port=6379)
return

def init_action(self):
if self.type == 'event':
self.topic = self.config.get("topic", "mudpi")
elif self.type == 'command':
self.shell = self.config.get("shell", False)

def trigger(self, value=None):
if self.type == 'event':
self.emitEvent()
elif self.type == 'command':
self.runCommand(value)
return

def emitEvent(self):
self.r.publish(self.topic, json.dumps(self.action))
return

def runCommand(self, value=None):
if value is None:
completed_process = subprocess.run([self.action], shell=self.shell)
else:
completed_process = subprocess.run([self.action, json.dumps(value)], shell=self.shell)
return
def __init__(self, config):
self.config = config
self.name = config.get("name", "Action")
self.type = config.get("type", "event")
self.key = config.get("key", None).replace(" ",
"_").lower() if config.get(
"key") is not None else self.name.replace(" ", "_").lower()
# Actions will be either objects to publish for events
# or a command string to execute
self.action = config.get("action")

try:
self.r = config["redis"] if config[
"redis"] is not None else redis.Redis(
host='127.0.0.1', port=6379)
except KeyError:
self.r = redis.Redis(host='127.0.0.1', port=6379)
return

def init_action(self):
if self.type == 'event':
self.topic = self.config.get("topic", "mudpi")
elif self.type == 'command':
self.shell = self.config.get("shell", False)

def trigger(self, value=None):
if self.type == 'event':
self.emit_event()
elif self.type == 'command':
self.run_command(value)
return

def emit_event(self):
self.r.publish(self.topic, json.dumps(self.action))
return

def run_command(self, value=None):
if value is None:
completed_process = subprocess.run([self.action], shell=self.shell)
else:
completed_process = subprocess.run(
[self.action, json.dumps(value)], shell=self.shell)
return
8 changes: 0 additions & 8 deletions config_load.py

This file was deleted.

5 changes: 5 additions & 0 deletions constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
PREVIOUS_LINE = "\x1b[1F"
RED_BACK = "\x1b[41;37m"
GREEN_BACK = "\x1b[42;30m"
YELLOW_BACK = "\x1b[43;30m"
RESET = "\x1b[0m"
46 changes: 23 additions & 23 deletions controls/arduino/button_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@

class ButtonControl(Control):

def __init__(self, pin, name=None, key=None, connection=default_connection, analog_pin_mode=False, topic=None, redis_conn=None):
super().__init__(pin, name=name, key=key, connection=connection, analog_pin_mode=analog_pin_mode, redis_conn=redis_conn)
self.topic = topic.replace(" ", "/").lower() if topic is not None else 'mudpi/controls/'+self.key
self.state_counter = 3
self.previous_state = 0
return
def __init__(self, pin, name=None, key=None, connection=default_connection, analog_pin_mode=False, topic=None, redis_conn=None):
super().__init__(pin, name=name, key=key, connection=connection, analog_pin_mode=analog_pin_mode, redis_conn=redis_conn)
self.topic = topic.replace(" ", "/").lower() if topic is not None else 'mudpi/controls/'+self.key
self.state_counter = 3
self.previous_state = 0
return

def init_control(self):
super().init_control()
def init_control(self):
super().init_control()

def read(self):
state = super().read()
if state == self.previous_state:
self.state_counter += 1
if self.state_counter % 2 == 0:
if state:
super().emitEvent(1)
elif self.state_counter == 2:
super().emitEvent(0)
else:
self.state_counter = 1
def read(self):
state = super().read()
if state == self.previous_state:
self.state_counter += 1
if self.state_counter % 2 == 0:
if state:
super().emitEvent(1)
elif self.state_counter == 2:
super().emitEvent(0)
else:
self.state_counter = 1

self.previous_state = state
return state
self.previous_state = state
return state

def readRaw(self):
return super().read()
def read_raw(self):
return super().read()
100 changes: 50 additions & 50 deletions controls/arduino/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,59 @@
import redis
from nanpy import (ArduinoApi, SerialManager)
import sys
sys.path.append('..')


default_connection = SerialManager()

# Base sensor class to extend all other arduino sensors from.
class Control():

def __init__(self, pin, name=None, connection=default_connection, analog_pin_mode=False, key=None, redis_conn=None):
self.pin = pin

if key is None:
raise Exception('No "key" Found in Control Config')
else:
self.key = key.replace(" ", "_").lower()

if name is None:
self.name = self.key.replace("_", " ").title()
else:
self.name = name
self.analog_pin_mode = analog_pin_mode
self.connection = connection
self.api = ArduinoApi(connection)
try:
self.r = redis_conn if redis_conn is not None else redis.Redis(host='127.0.0.1', port=6379)
except KeyError:
self.r = redis.Redis(host='127.0.0.1', port=6379)
return

def init_control(self):
#Initialize the control here (i.e. set pin mode, get addresses, etc)
self.api.pinMode(self.pin, self.api.INPUT)
pass

def read(self):
#Read the sensor(s), parse the data and store it in redis if redis is configured
return self.readPin()

def readRaw(self):
#Read the sensor(s) but return the raw data, useful for debugging
pass

def readPin(self):
#Read the pin from the ardiuno. Can be analog or digital based on "analog_pin_mode"
data = self.api.analogRead(self.pin) if self.analog_pin_mode else self.api.digitalRead(self.pin)
return data

def emitEvent(self, data):
message = {
'event':'ControlUpdate',
'data': {
self.key:data
}
}
print(message["data"])
self.r.publish('controls', json.dumps(message))
def __init__(self, pin, name=None, connection=default_connection, analog_pin_mode=False, key=None, redis_conn=None):
self.pin = pin

if key is None:
raise Exception('No "key" Found in Control Config')
else:
self.key = key.replace(" ", "_").lower()

if name is None:
self.name = self.key.replace("_", " ").title()
else:
self.name = name
self.analog_pin_mode = analog_pin_mode
self.connection = connection
self.api = ArduinoApi(connection)
try:
self.r = redis_conn if redis_conn is not None else redis.Redis(host='127.0.0.1', port=6379)
except KeyError:
self.r = redis.Redis(host='127.0.0.1', port=6379)
return

def init_control(self):
#Initialize the control here (i.e. set pin mode, get addresses, etc)
self.api.pinMode(self.pin, self.api.INPUT)
pass

def read(self):
#Read the sensor(s), parse the data and store it in redis if redis is configured
return self.read_pin()

def read_raw(self):
#Read the sensor(s) but return the raw data, useful for debugging
pass

def read_pin(self):
#Read the pin from the ardiuno. Can be analog or digital based on "analog_pin_mode"
data = self.api.analogRead(self.pin) if self.analog_pin_mode else self.api.digitalRead(self.pin)
return data

def emitEvent(self, data):
message = {
'event':'ControlUpdate',
'data': {
self.key:data
}
}
print(message["data"])
self.r.publish('controls', json.dumps(message))
50 changes: 25 additions & 25 deletions controls/arduino/potentiometer_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@

class PotentiometerControl(Control):

def __init__(self, pin, name=None, key=None, connection=default_connection, analog_pin_mode=True, topic=None, reading_buffer=3, redis_conn=None):
super().__init__(pin, name=name, key=key, connection=connection, analog_pin_mode=analog_pin_mode, redis_conn=redis_conn)
self.previous_state = 0
# Reading buffer helps prevent multiple events when values are floating between small amounts
self.reading_buffer = reading_buffer
return

def init_control(self):
super().init_control()
# Set initial state to prevent event on boot
self.previous_state = super().read()

def read(self):
state = super().read()

if (state < self.previous_state - self.reading_buffer) or (state > self.previous_state + self.reading_buffer):
# Value changed
# print('{0}: {1}'.format(self.name, state))
super().emitEvent(state)

self.previous_state = state
return state

def readRaw(self):
return super().read()
def __init__(self, pin, name=None, key=None, connection=default_connection, analog_pin_mode=True, topic=None, reading_buffer=3, redis_conn=None):
super().__init__(pin, name=name, key=key, connection=connection, analog_pin_mode=analog_pin_mode, redis_conn=redis_conn)
self.previous_state = 0
# Reading buffer helps prevent multiple events when values are floating between small amounts
self.reading_buffer = reading_buffer
return

def init_control(self):
super().init_control()
# Set initial state to prevent event on boot
self.previous_state = super().read()

def read(self):
state = super().read()

if (state < self.previous_state - self.reading_buffer) or (state > self.previous_state + self.reading_buffer):
# Value changed
# print('{0}: {1}'.format(self.name, state))
super().emitEvent(state)

self.previous_state = state
return state

def read_raw(self):
return super().read()

Loading