Files @ 22b6999f8bdd
Branch filter:

Location: HydroBot/hydrobot-software/hydrobot.py

matthewreed
Added timers in the config file
import sys
import time
import _thread
import ast
import configparser
from canard import can, messaging
from canard.hw import socketcan
from canard.file import jsondb
from influxdb import InfluxDBClient
from apscheduler.schedulers.background import BackgroundScheduler

#TODO
#fix temperature offset
#database series helper
#database time interval logging
#add system name to database

config = configparser.ConfigParser(allow_no_value = True)
config.read("hydrobot.conf")
DEBUG_CAN = config.getboolean("debug", "can")
DEBUG_CAN_DETAIL = config.getboolean("debug", "can_detail")

class Database:
    
    def __init__(self):
        host = config.get("database", "host")
        port = config.get("database", "port")
        username = config.get("database", "username")
        password = config.get("database", "password")
        database = config.get("database", "database")
        self.name = config.get("system", "name")
        self.client = InfluxDBClient(host, port, username, password, database)

    def log_data(self, msgdb, message):
        if message == msgdb.AirSense:
            json_body = [
                {
                    "measurement": self.name + "_air_temp",
                    "fields": {
                        "value": (float)(message.Temperature.value)
                    }
                },
                {
                    "measurement": self.name + "_air_humidity",
                    "fields": {
                        "value": (float)(message.Humidity.value)
                    }
                },
                {
                    "measurement": self.name + "_air_pressure",
                    "fields": {
                        "value": (float)(message.Pressure.value)
                    }
                }
            ]
            self.client.write_points(json_body)
        if message == msgdb.RelayDriveIn:
            json_body = [
                {
                    "measurement": self.name + "_input_1",
                    "fields": {
                        "value": (float)(message.Input1.value)
                    }
                },
                {
                    "measurement": self.name + "_input_2",
                    "fields": {
                        "value": (float)(message.Input2.value)
                    }
                },
                {
                    "measurement": self.name + "_input_3",
                    "fields": {
                        "value": (float)(message.Input3.value)
                    }
                },
                {
                    "measurement": self.name + "_input_4",
                    "fields": {
                        "value": (float)(message.Input4.value)
                    }
                }
            ]
            self.client.write_points(json_body)


class CanBus:
    
    def __init__(self, database):
        
        self.database = database

        self.dev = socketcan.SocketCanDev("can0")
        
        parser = jsondb.JsonDbParser()
        self.msgdb = parser.parse('hydrobot_can.json')
        
        self.temp_msg = self.msgdb.AirSense
        self.relay_msg = self.msgdb.RelayDriveIn
        self.relay_send_msg = self.msgdb.RelayDriveOut
        
    def start(self):
        self.dev.start()
        
    def start_receive(self):
        _thread.start_new_thread(self.process_can, ())

    def process_can(self):
        while True:
            frame = self.dev.recv()
            message = self.msgdb.decode(frame)
            if message:
                if DEBUG_CAN:
                    print("Received CAN message! ID: " + hex(message.id))
                for s in message._signals.values():
                    if DEBUG_CAN_DETAIL:
                        print(s)
                        print(s.value)
                    self.database.log_data(self.msgdb, message)
                
    def send_can(self):
        self.relay_send_msg.Nothing.value = 0
        if self.relay_send_msg.Output1.value == 0:
            self.relay_send_msg.Output1.value = 1
        else:
            self.relay_send_msg.Output1.value = 0
        self.relay_send_msg.Output2.value = 1
        self.relay_send_msg.Output3.value = 1
        self.relay_send_msg.Output4.value = 1
        if DEBUG_CAN:
            print("Send CAN message! ID: " + hex(self.relay_send_msg.id))
        if DEBUG_CAN_DETAIL:
            print(self.relay_send_msg)
        self.dev.send(self.relay_send_msg.encode())
        
    def set_output(self, module, output, state):
        msg = self.msgdb.lookup_message(module)
        msg.lookup_signal(output).value = state
        print(msg)
        self.dev.send(msg.encode())

def main():
    
    database = Database()
    canbus = CanBus(database)
    canbus.start()
    canbus.start_receive()
    
    scheduler = BackgroundScheduler()
    
    for section in config.sections():
        if "timer" in section:
            items = config.items(section)
            for item in items:
                if item[0] == 'trigger':
                    trigger = item[1]
                if item[0] == 'module':
                    module = item[1]
                if item[0] == 'output':
                    output = item[1]
                if item[0] == 'on_time':
                    on_time = ast.literal_eval(item[1])
                if item[0] == 'off_time':
                    off_time = ast.literal_eval(item[1])
                if item[0] == 'on_duration':
                    on_duration = ast.literal_eval(item[1])
            if trigger == 'cron':
                scheduler.add_job(canbus.set_output, trigger, [module, output, 1], day = on_time[0], day_of_week = on_time[1], hour = on_time[2], minute = on_time[3], second = on_time[4])
                scheduler.add_job(canbus.set_output, trigger, [module, output, 0], day = off_time[0], day_of_week = off_time[1], hour = off_time[2], minute = off_time[3], second = off_time[4])
            if trigger == 'interval':
                scheduler.add_job(canbus.set_output, trigger, [module, output, 1], weeks = on_duration[0], days = on_duration[1], hours = on_duration[2], minutes = on_duration[3], seconds = on_duration[4])
    
    scheduler.start()

    while True:
        
        time.sleep(1)
        

if __name__ == "__main__":
    main()