# Embedded UE3
# 1. Actuators
## a)
Then investigate the script blink.py and run it. Describe its behavior and add a
picture of your setup
```python
import RPi.GPIO as GPIO
from time import sleep
import logging
# setup logging
logger = logging.getLogger(__name__)
logging.basicConfig(level="INFO")
# set GPIO Mode
GPIO.setmode(GPIO.BCM)
# setup GPIO pins
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(25, GPIO.OUT)
GPIO.output(24, False)
GPIO.output(25, False)
pin=24
try:
while True:
button_state = GPIO.input(18)
logger.info("button state is %s (pressed=%s)",button_state,not bool(button_state))
if button_state == False:
pin=24
else:
pin=25
GPIO.output(pin, True)
sleep(1)
GPIO.output(pin, False)
sleep(1)
except KeyboardInterrupt:
logger.info("cleaning up ...")
GPIO.cleanup()
```
**Setup:**

**Describe its behavior:**
- On button press, state will be toggled (which is read from GPIO input pin 18). When the button is not pressed, the red LED (pin 24) will blink. When the button is pressed, the green LED (pin 25) will blink.
**Testen**: Pin auf 5V pin setzen. Siehe reference
Reference:
https://de.pinout.xyz/pinout/pin2_5v_stromversorgung#
## b)
Investigate the script blink threaded.py and run it. Describe the differences
to the previous script:
```python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
import threading
import logging
# setup logging
logger = logging.getLogger(__name__)
logging.basicConfig(level="INFO")
led_pin=24
class Button():
def __init__(self, channel):
self.channel = channel
self._thread=threading.Thread(name='button',target=self.run)
self._thread.deamon = True
self._thread_active = True
self._thread.start()
def run(self):
logger.info("button thread started")
previous = 1
current = 0
while self._thread_active:
time.sleep(0.01)
current = GPIO.input(self.channel)
logger.debug("current %s previous %s",current,previous)
if current==1 and previous==0:
logger.info("button was pressed and released")
self.onButtonPress()
previous = current
def onButtonPress(self):
global led_pin
if led_pin==24:
led_pin=25
else:
led_pin=24
GPIO.output(24, False)
GPIO.output(25, False)
def stop(self):
logger.debug("stopping thread")
self._thread_active = False
try:
# setup gpio
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
button=Button(18)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(25, GPIO.OUT)
GPIO.output(24, False)
GPIO.output(25, False)
while True:
# toggle gpio
GPIO.output(led_pin, True)
time.sleep(1)
GPIO.output(led_pin, False)
time.sleep(1)
except KeyboardInterrupt:
button.stop()
logger.info("stopping ...")
time.sleep(1)
GPIO.cleanup()
```
**Differences:**
- Toggling instead of holding.
- Toggling after fallen edge
- Button press is detected faster (because it's only sleeping for 0.01s instead of 1s)
nonblocking
# 2. Connectivity
## a)
**Change the matriculation number:**
```python
def on_connect(client, userdata, flags, rc):
logger.info('Connected with result code %s',str(rc))
client.subscribe("12024183", qos=0)
```
Complete the source code of remotecontrol.py so that it correctly switches on
and off the lights, based on received messages
```python
#!/usr/bin/python
from __future__ import division
import time
import paho.mqtt.client as mqtt
import logging
import RPi.GPIO as GPIO
from at.jku.pervasive.eps.mymqttmessages.mymqttmessages_pb2 import *
# setup logging
logger = logging.getLogger(__name__)
logging.basicConfig(level="INFO")
# setup gpio
GPIO.setmode(GPIO.BCM)
LED_RED=25
LED_GREEN=24
GPIO.setup(LED_RED, GPIO.OUT)
GPIO.setup(LED_GREEN, GPIO.OUT)
GPIO.output(LED_RED, False)
GPIO.output(LED_GREEN, False)
# mqtt connect callback function
def on_connect(client, userdata, flags, rc):
logger.info('Connected with result code %s',str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("12024183", qos=0)
# mqtt message received callback function
def on_message(client, userdata, msg):
commandString=str(msg.payload)
proto_msg = PBMessage()
try:
proto_msg.ParseFromString(msg.payload)
if proto_msg.HasField('ledControl'):
logger.debug('got message at %s with content %s',str(msg.topic),commandString)
logger.info('got message from %s (with target %s)',proto_msg.source,proto_msg.target)
logger.info('ledControl numberic %s %s %s',proto_msg.ledControl.action,proto_msg.ledControl.led,proto_msg.ledControl.toggleRateHz)
logger.info('ledControl Info %s %s %s',LedAction.Name(proto_msg.ledControl.action),Led.Name(proto_msg.ledControl.led),proto_msg.ledControl.toggleRateHz)
led_pin=-1
# Set pin
if Led.Value('RED')==proto_msg.ledControl.led:
led_pin=LED_RED
elif Led.Value('GREEN')==proto_msg.ledControl.led:
led_pin=LED_GREEN
else:
logger.error('cannot map led %s to pin',Led.Name(proto_msg.ledControl.led))
return
# Set action
# TODO: Read action from message and control LED
if proto_msg.ledControl.action == LedAction.Value("OFF"):
GPIO.output(led_pin, 0) #turn off
elif proto_msg.ledControl.action == LedAction.Value("ON"):
GPIO.output(led_pin, 1) #turn on
elif proto_msg.ledControl.action == LedAction.Value("TOGGLE"):
current = GPIO.input(led_pin)
GPIO.output(led_pin, not current)
else:
GPIO.output(led_pin,0)
# end of ledControl processing
else:
logger.warn('got message at %s with content %s',str(msg.topic),commandString)
except:
logger.warning('Unable to decode message: No valid ProtoBuf Msg received')
# setup mqtt
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
# connect mqtt
client.connect("iot.soft.uni-linz.ac.at", 1883, 60)
try:
client.loop_forever()
except (KeyboardInterrupt, SystemExit):
logger.info('disconnecting ...')
client.disconnect()
time.sleep(1)
GPIO.cleanup()
```
TODO:
- Execute and collect
## b)
```java
public class ProtobufMqttProgram {
// embeddedsystems2019
private static final String DEFAULT_TOPIC = "12024183";
public static void main(String[] args) {
ProtobufMqttProgram connector = new ProtobufMqttProgram();
try {
Thread.sleep(2000);
// unsubscribe to not consume sent messages
// connector.sampleClient.unsubscribe(DEFAULT_TOPIC);
// qos = 2 (exactly once)
// TODO: Publish different LedControl Messages
connector.sendLedControl(Led.RED, LedAction.ON, 0);
Thread.sleep(5000);
// Publish LedControl with color=red, action=off, togglerate=0
connector.sendLedControl(Led.RED, LedAction.OFF, 0);
Thread.sleep(5000);
// Publish LedControl with color=green, action=on, togglerate=0
connector.sendLedControl(Led.GREEN, LedAction.ON, 0);
Thread.sleep(5000);
// Publish LedControl with color=green, action=off, togglerate=0
connector.sendLedControl(Led.GREEN, LedAction.OFF, 0);
Thread.sleep(5000);
connector.close();
} catch (MqttException e) {
processEx(e);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
```
```
```
Logs:
```
INFO:__main__:Connected with result code 0
INFO:__main__:got message from 3576804469 (with target 0)
INFO:__main__:ledControl numberic 1 0 0
INFO:__main__:ledControl Info ON RED 0
INFO:__main__:got message from 3576804469 (with target 0)
INFO:__main__:ledControl numberic 0 0 0
INFO:__main__:ledControl Info OFF RED 0
INFO:__main__:got message from 3576804469 (with target 0)
INFO:__main__:ledControl numberic 1 1 0
INFO:__main__:ledControl Info ON GREEN 0
INFO:__main__:got message from 3576804469 (with target 0)
INFO:__main__:ledControl numberic 0 1 0
INFO:__main__:ledControl Info OFF GREEN 0
```
# 3. Message Format
## a)
Protobuf messages:
```
connector.sendLedControl(Led.RED, LedAction.ON, 0);
connector.sendLedControl(Led.RED, LedAction.OFF, 0);
connector.sendLedControl(Led.GREEN, LedAction.ON, 0);
connector.sendLedControl(Led.GREEN, LedAction.OFF, 0);
```
Output Protobuf
```
INFO a.j.p.eps.ProtobufMqttProgram - Connecting to broker: tcp://iot.soft.uni-linz.ac.at:1883
INFO a.j.p.eps.ProtobufMqttProgram - connected to tcp://iot.soft.uni-linz.ac.at:1883
INFO a.j.p.eps.ProtobufMqttProgram - message size 11
WARN a.j.p.eps.ProtobufMqttProgram - got led control from 997924158 with target 0
INFO a.j.p.eps.ProtobufMqttProgram - message size 9
WARN a.j.p.eps.ProtobufMqttProgram - got led control from 997924158 with target 0
INFO a.j.p.eps.ProtobufMqttProgram - message size 13
WARN a.j.p.eps.ProtobufMqttProgram - got led control from 997924158 with target 0
INFO a.j.p.eps.ProtobufMqttProgram - message size 11
WARN a.j.p.eps.ProtobufMqttProgram - got led control from 997924158 with target 0
```
JSON Messages:
```
{"LED":"RED","ACTION":"TOGGLE","TOGGLERATE":"5"}
{\"LED\":\"GREEN\",\"ACTION\":\"ON\",\"TOGGLERATE\":\"0\"}
{\"LED\":\"BLUE\",\"ACTION\":\"OFF\",\"TOGGLERATE\":\"0\"}
{\"LED\":\"GREEN\",\"ACTION\":\"ON\",\"TOGGLERATE\":\"0\"}
{\"LED\":\"RED\",\"ACTION\":\"OFF\",\"TOGGLERATE\":\"0\"}
{\"LED\":\"BLUE\",\"ACTION\":\"TOGGLE\",\"TOGGLERATE\":\"1\"}
```
Output JSON
```
INFO at.jku.pervasive.eps.TextMqttProgram - Connecting to broker: tcp://iot.soft.uni-linz.ac.at:1883
INFO at.jku.pervasive.eps.TextMqttProgram - connected to tcp://iot.soft.uni-linz.ac.at:1883
INFO at.jku.pervasive.eps.TextMqttProgram - message size 48
INFO at.jku.pervasive.eps.TextMqttProgram - message size 46
INFO at.jku.pervasive.eps.TextMqttProgram - message size 46
INFO at.jku.pervasive.eps.TextMqttProgram - message size 46
INFO at.jku.pervasive.eps.TextMqttProgram - message size 45
INFO at.jku.pervasive.eps.TextMqttProgram - message size 49
```
## b)
### Protobuf
Uses binary encoding
- Enums (like LedAction) can be represented with minimal bit amount
```
Led.RED, LedAction.ON, 0
```
### JSON
Uses ASCII encoding
- Instead of representing actions as an enum, they are represented as strings. So we need 6 bytes instead of 2 bits (which is rounded up to 1 byte).
- There's also lots of useless information needed to structure the message (':' and '{}')
```
"{\"LED\":\"RED\",\"ACTION\":\"TOGGLE\",\"TOGGLERATE\":\"5\"}"
```