I just realized that the cut off time for submission is 11:59 PM GMT which is a bit sooner than I expected, so here be what I have thus far.
After getting the connections completed with the Pi Rack, I moved to working on the Automation application of the Feeder System I have been working on. This has included implementing Mosquitto, Paho, and MQTT for communication between OpenHAB and the feeder system. With this, I can adjust the timer and setting locally on the Feeder System as well as change the Timer, Run the Feeder Manually, view the Pi CAM remotely and be notified when there is motion in the stall.
MQTT Phao and Mosquitto
Thus far in the config, I have 3 Topics that get updated at various intervals and events.
feeder/timer - Used to notify topic Subscribers that an update to the timer has been performed. This can be accomplished locally via the Pi Face Display and Control interface or remotely from open HAB.
feeder/manual - Used to Trigger the feeder system to run in Manual mode thus bypassing any timer settings
feeder/motion - Used to notify that there is moved in the Stall via a PIR sensor connected to the Pi Face Digital 2.
feeder/timer
Within OpenHAB, to handle the user input for setting the Feeder Timer remotely, the following config was implemented.
The site was very helpful in getting the Timer section completed:
https://github.com/openhab/openhab/wiki/AlarmClock
The Initial interface for the OpenHAB config displays the Feeder Timer, an option to set the Timer, Stall CAM (Both Video and Still cam options), The iLumi BLE Lights and EnOcean Energy Harvesting Switches.
From the Stall Timer, the user can Set the Timer by setting the Set_Timer switch to on. The will grab the Timer that is site from the OpenHAB interface and send it to the feeder/timer topic which is picked up by the Feeder system. Also, the user can run the Feeder manually from the interface. And, if there is motion, the Stall Motion indicator will be lit.
From the interface, the user selects the Time (Hour/Min) and the day to run the timer and once selected, click the Set Timer Switch.
Sitemap
sitemap home label="Smart Stall" { Frame label="Stall Timer" { Frame label="Feeder Timer" { Text label="Timer [%s]" item=timerMessage icon="clock" { Frame label="Run Mode" { Switch item=Set_Timer label="Set Timer" Switch item=Manual_Run label="Manual Run" Switch item=Motion_Alert label="Stall Motion" Text item=Motion_Detect } Frame label="Time" { Setpoint item=Set_Hour minValue=0 maxValue=23 step=1 Setpoint item=Set_Minute minValue=0 maxValue=55 step=5 } Frame label="Days" { Switch item=timerMonday Switch item=timerTuesday Switch item=timerWednesday Switch item=timerThursday Switch item=timerFriday Switch item=timerSaturday Switch item=timerSunday } } }
Items
Group iLumi Group Feeder Group DaysOfWeek String Feeder_Timer "Get Timer [%s]" <clock> (Feeder, iLumi) {mqtt="<[jiot2:feeder/timer:state:default]"} Switch Set_Timer <switch> (Feeder, iLumi) String Send_Timer "[%s]" (Feeder, iLumi) { mqtt=">[jiot2:feeder/timer:command:*:default]" } Switch Manual_Run <switch> (Feeder, iLumi) String Run_Manual "[%s]" (Feeder, iLumi) { mqtt=">[jiot2:feeder/manual:command:*:default]" } Number Set_Hour "Hour [%d]" <clock> (Feeder, iLumi) Number Set_Minute "Minute [%d]" <clock> (Feeder, iLumi) Dimmer Set_Day "Day [%s %%]" (Feeder, iLumi) String New_Day "Day [%s]" (Feeder, iLumi) String New_Hour "Hour [%d]" (Feeder, iLumi) String timerMessage "%s" Switch Motion_Alert <siren> (Feeder, iLumi) String Motion_Detect "Switch Motion[%s]" (Feeder, iLumi) { mqtt="<[jiot2:feeder/motion:state:default]" } Switch timerMonday "Monday" <switch> (DaysOfWeek) Switch timerTuesday "Tuesday" <switch> (DaysOfWeek) Switch timerWednesday "Wednesday" <switch> (DaysOfWeek) Switch timerThursday "Thursday" <switch> (DaysOfWeek) Switch timerFriday "Friday" <switch> (DaysOfWeek) Switch timerSaturday "Saturday" <switch> (DaysOfWeek) Switch timerSunday "Sunday" <switch> (DaysOfWeek)
Timer Rules
var String timerToMQTT = "" rule "Initialization" when System started then postUpdate(Set_Hour, 6) postUpdate(Set_Minute, 15) postUpdate(timerMonday, ON) postUpdate(timerTuesday, OFF) postUpdate(timerWednesday, OFF) postUpdate(timerThursday, OFF) postUpdate(timerFriday, OFF) postUpdate(timerSaturday, OFF) postUpdate(timerSunday, OFF) postUpdata(Manual_Run, OFF) postUpdata(Motion_Alert, OFF) end er rules
rule "Set Timer" when Item Set_Hour changed or Item Set_Minute changed then logInfo("Set Timer", "Set Timer") var String msg = "" var String day = "" var String ampm = "" var hour = Set_Hour.state as DecimalType var minute = Set_Minute.state as DecimalType if (timerMonday.state == ON) { day = "Mon" } if (timerTuesday.state == ON) { day = "Tue" } if (timerWednesday.state == ON) { day = "Wed" } if (timerThursday.state == ON) { day = "Thu" } if (timerFriday.state == ON) { day = "Fri" } if (timerSaturday.state == ON) { day = "Sat" } if (timerSunday.state == ON) { day = "Sun" } if (hour < 10) { msg = "0" } msg = msg + Set_Hour.state.format("%d") + ":" if (hour >= 12) {ampm = "PM"} if (hour < 12) {ampm = "AM"} if (minute < 10) { msg + msg = "0" } msg = msg + Set_Minute.state.format("%d") msg = day + " " + msg + " " + ampm postUpdate(timerMessage, msg) timerToMQTT = msg end rule "Set Feed Timer" when Item Set_Timer changed from OFF to ON then var String feed_timer //feed_timer = "Mon 07:30 AM" sendCommand(Send_Timer, timerToMQTT) end
rule "Manual Feeder Run" when Item Manual_Run changed from OFF to ON then var String set_manual = "" set_manual = "Run" sendCommand(Run_Manual, set_manual) end rule "Manual Feeder Stop" when Item Manual_Run changed from ON to OFF then var String set_manual = "" set_manual = "Stop" sendCommand(Run_Manual, set_manual) end rule "Motion Detected" when Item Motion_Detect changed then var String motion_message = "" logInfo("Motion Detected", "In Da Motion") motion_message = Motion_Detect.state.toString logInfo("Motion Detected", motion_message) if (motion_message == "Motion Detected") { sendCommand(Motion_Alert, ON) } else { sendCommand(Motion_Alert, OFF) } end
OpenHAB.cfg
mqtt:jiot2.url=tcp://192.168.2.130:1883 # Optional. Client id (max 23 chars) to use when connecting to the broker. # If not provided a default one is generated. #mqtt:<broker>.clientId=<clientId> mqtt:jiot2.clientId=FeedMQTT mqtt-eventbus:broker=jiot2 mqtt-eventbus:commandPublishTopic=feeder/timer/${item}/command mqtt-eventbus:commandSubscribeTopic=feeder/timer/${item}/state mqtt-eventbus:commandPublishTopic=feeder/manual/${item}/command mqtt-eventbus:commandSubscribeTopic=feeder/manual/${item}/state mqtt-eventbus:commandSubscribeTopic=feeder/motion/${item}/state
Feeder System Paho config
def send_mqtt(message_dict): mqttc = mqtt.Client('python_publisher') mqttc.connect('192.168.2.130', 1883) #message_json2str = json.dumps(message_dict) hourTemp = str(timer_dict['hour']).rjust(2, '0') minTemp = str(timer_dict['min']).rjust(2, '0') message_json2str = timer_dict['day'] + " " + hourTemp + ":" + minTemp + " " + timer_dict['ampm'] mqttc.publish('feeder/timer', message_json2str, retain=True) t.sleep(2) mqttc.disconnect() # The callback for when the client receives a CONNACK response from the server def on_connect(client, userdata, rc): print("Connected with result code "+str(rc)) # Subscribing in on_connect() means that we lose the connect and # reconnect then subscriptions will be renewed client.subscribe([("feeder/timer", 0), ("feeder/manual", 0)]) #client.subscribe("feeder/timer") #client.subscribe("feeder/manual") # The callback forwhen a PUBLISH message is received from the server. def on_message(client, userdata, msg): hourTemp = "" minTemo = "" man_run = "" current_timer = "" #msg_read ="" msg_read = msg.payload.decode('utf-8') #print(msg.topic+" "+str(msg.payload)) print(msg.topic+" "+msg_read) if (msg.topic == "feeder/manual"): man_run = msg_read #man_run = str(msg.payload) print("feeder/manual = %s" % man_run) if ('Run' in man_run): runManual() #client.disconnect() if (msg.topic == "feeder/timer"): timer_data = msg_read if os.path.isfile('timer.json'): with open('timer.json') as datafile: current_timer = json.load(datafile) print("New time message %s " % timer_data) timer_data = timer_data.split() print("Current Timer %s " % current_timer) if current_timer != timer_data: print("New Timer") with open('timer.json', 'w') as outfile: json.dump(timer_data, outfile) timer_dict['day'] = timer_data[0].strip() hour_min = timer_data[1].split(":") timer_dict['hour'] = hour_min[0] timer_dict['min'] = hour_min[1] timer_dict['ampm'] = timer_data[2] saveTimerData(timer_dict) showTimer() #client.disconnect() #hourTemp = str(timer_dict['hour']).rjust(2, '0') #minTemp = str(timer_dict['min']).rjust(2, '0')] #message_json2str = timer_dict['day'] + " " + hourTemp + ":" + minTemp + " " + timer_dict['ampm'] client.disconnect() def getMQTTTimer(): mqttc = mqtt.Client() mqttc.on_connect = on_connect mqttc.on_message = on_message mqttc.connect('192.168.2.130', 1883, 60) ''' if (mqttc.connected is not False): mqttc.connect('192.168.2.130', 1883, 60) #mqttc.loop_start() ''' mqttc.loop_forever(timeout=1.0, max_packets=2, retry_first_connection=False) mqttc.disconnect(
Motion Sensor to Pi Face Digital 2
The sensor I used for the Motion Sensing is the Parallax PI Sensor rev B. This is connected to the Pi Face Digital 2 Input 3, 5V and Ground. (NOTE: Since the Digital 2 Inputs are by default pulled up to 5V, I ended up having to put a 10K resistor between GND and Pin 3 to pull the pin low when the PIR sensor was on.)
PiFace Digital IO Config:
import pifacedigitalio as pdio def detectMotion(): MOTION = 0 NO_MOTION = 1 pri1 = NO_MOTION pdio.init() t.sleep(1) while True: pir1 = pdio.digital_read(3,1) if pir1 is MOTION: print ("Motion Detected!") send_message(topic_motion, feeder_broker, "Motion Detected") t.sleep(1)
This was started as a Process in Python so it would run parallel in the background to the main app:
p = Process(target=getMQTTTimer) m = Process(target=detectMotion) p.start() p.join() m.daemon = False m.start()
With all of that, this is what it looks like in the raw, nothing in case at this point.
This has been an awesome adventure and I appreciate the opportunity to use the tools given to create a project; I just wish I could have completed it in the time allotted. I'll keep working on this and hopefully get something that is complete be years end.
Thanks,
Jon
Top Comments