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.

 

OpenHAB MQTT

 

 

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.

 

Smart Feeder Timer setting

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