16. Interface and application programming¶
This week we have to write an application that interfaces with an input &/or output device that we made .
I use the input board I made on week 11 and 12
I want to make a simple connection with a computer with Pyserial then use one of the growing and powerfull system Home Assistant . With Home Assistant, I’m integrating a twitter account and a text-to-speech module.
Board¶
The board is simply sending by serial the value received by the phototransistor. For more explanation visit week 11 and 12
Here is a reminder of the code :
#include <SoftwareSerial.h> //TX , PA0 , could be A0, 0 , 10 //RX , PA1 , could be A1 , 1 , 9 const int mosfet = 7; // connected to PA7 or 7 in arduino const int phototransistor = A3 ; // connected to PA3 , A3 in arduino int photovalue = 0; int timing = 1000 * 10; SoftwareSerial mySerial(0, A1); // RX, TX void setup() { mySerial.begin(9600); pinMode(mosfet, OUTPUT); pinMode(phototransistor, INPUT); } void loop() { photovalue = analogRead(phototransistor); mySerial.println(photovalue); delay(timing); }
I have just changed the timing value to 10000 to have a message every 10 seconds.
Pyserial¶
I install raspbian on a Raspberry Pi. They are many tutorial on how to do it, one of them is https://www.raspberrypi.org/documentation/installation/installing-images/
Then I connect the board with an FTDI to usb connection of the Raspberry Pi.
The first step is to know if the usb connection is recognised by the linux system. The command lsusb display all connected devices.
I can guess that the Bus 001 Device 005 is the FTDI connection.
If you are not sure : connect the usb cable and run the lsusb command then disconnect the usb cable and run again the lsusb command. A line should have change.
Normally Python and pip are already installed with raspbian. The following line will add the pyserial package.
python -m pip install pyserial
Then I download a code miniterm , it’s a serial terminal written in python with pyserial.
wget https://github.com/pyserial/pyserial/blob/master/serial/tools/miniterm.py sudo python miniterm.py
With that tool, I am able to check that the serial connection is working correctly with pyserial but also to find the right port.
The name of my port is /dev/ttyUSB0 , it is also detecting that its 9600,8,N,1 related to the baudrate, bit lenght, parity and carriage return.
Then it display the content of the serial exchange between the computer and the board.
Then I write a simple python code that will interpret the sensor value by displaying jour or nuit depending on the photoresistance value.
It’s some kind of reference to the movie les visiteurs
content of simple_pyserial.py
import serial from serial.tools.list_ports import comports from serial.tools import hexlify_codec ser = serial.Serial('/dev/ttyUSB0') # open serial port while True: line = ser.readline() # read a '\n' terminated line if int(line) < 100: print("jour") if int(line) > 700: print("nuit") print(line)
You can launch the code with this command :
sudo python simple_pyserial.py
Python is a powerfull langage.
The following part on Homeassitant is mainly based on Python.
Homeassistant¶
Home Assistant is a rapidly growing system. The website describe Home Assistant as an Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server.
One of the main advantage is that you can install it on a rapsberry Pi, a cheap computer. It is powerfull enought to run a huge amount of code.
The main goal of Home Assistant was to automate your house, also named in french Domotique. But I think the system has gone far beyond a traditional home automation system.
The information to install https://www.home-assistant.io/docs/installation/raspberry-pi/
The commands to install in a virtual environment with a fresh raspbian
sudo apt-get update sudo apt-get upgrade -y sudo apt-get install python3 python3-venv python3-pip libffi-dev libssl-dev sudo useradd -rm homeassistant -G dialout,gpio cd /srv sudo mkdir homeassistant sudo chown homeassistant:homeassistant homeassistant sudo -u homeassistant -H -s cd /srv/homeassistant python3 -m venv . source bin/activate python3 -m pip install wheel pip3 install homeassistant hass
Then you are able to connect to a webpage on the ipadress of the RPi on the port 8123 , in my case http://10.1xx.0.42:8123/ (for security reasons, I hide some numbers with X)
The frist time you launch Home Assistant it can takes up to 10 minutes to install all the modules, so take your time…
On the first launch, since recently, you have to create a username and a password.
Then the visual interface should not be too crowded. By default you will have a meteo module, a sun module that display if the sun is set based on your GPS coordinate, and a kind of presence detector.
In my case it also detect a media player. So if like me, you have several UPNP enabled device, they could be recognise automatically. Here a Volumio player, located on http://zik.local/
Then you can edit the configuration.yaml file to add sensors.
cd /home/homeassistant/.homeassistant sudo nano configuration.yaml
If you want to run the system at each boot, you can follow those instructions https://www.home-assistant.io/docs/autostart/ But in the scope of this page, I restarted and started the software manually with
sudo -u homeassistant -H -s source /srv/homeassistant/bin/activate hass
Add a Serial Sensor object.¶
The Serial Sensor object is described on https://www.home-assistant.io/components/serial/
By adding those lines in the configuration.yaml file located in /home/homeassistant/.homeassistant , you will enable a serial sensor.
- platform: serial serial_port: /dev/ttyUSB0
So the file will look like
homeassistant: # Name of the location where Home Assistant is running name: Home # Location required to calculate the time the sun rises and sets latitude: 49.4668 longitude: 2.07255 # Impacts weather/sunrise data (altitude above sea level in meters) elevation: 0 # metric for Metric, imperial for Imperial unit_system: metric # Pick yours from here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones time_zone: Europe/Paris # Customization file customize: !include customize.yaml # Configure a default setup of Home Assistant (frontend, api, etc) default_config: # Uncomment this if you are using SSL/TLS, running in Docker container, etc. # http: # base_url: example.duckdns.org:8123 # Discover some devices automatically discovery: # Sensors sensor: # Weather prediction - platform: yr - platform: serial serial_port: /dev/ttyUSB0 #value_template: "{{ (states('sensor.serial_sensor') + 1.0 ) | round(1) }}" #value_template: "{{ (((states('sensor.serial_sensor') | float * 5 / 1024 ) - 0.5) * 100) | round(1) }}" # Text to speech tts: - platform: google_translate group: !include groups.yaml automation: !include automations.yaml script: !include scripts.yaml
Be aware that in my case the board is connected with an FTDI on port /dev/ttyUSB0 .
With the YAML format, indentation is really important and it is made with 2 space character and not with a tabulation character. The # character is for comment. Here I let 2 lines that I have commented to have some examples of a template. That means you can make directly some operations on the data.
As this modification is made on the configuration.yaml file. You will have to restart the whole system. Be aware that Home Assistant can takes time to install or update the components you have modify or install in the configuration.yaml file . Sometimes a complete reboot is necessary to update and install some components.
If everything went correctly, you should see a new module on your webpage.
By default you will see the value directly displayed above the sensor name, in this case 1003 for the Serial Sensor.
You can add differents kind of visualisation to display the data.
And in each screen you can add what they call a card .
Or you could build from scratch your own card. And you can customize the card : what data to display, and several parameters .
As Homeassistant become more and more user friendly, you can add several sensor throught the interface. But it’s more powerfull to add or edit directly the configuration.yaml and the automation.yaml files.
Doing it that way is easy but is extremly limited and you have access to only a few part of the possible integration.
To take a look at all the available integrations : https://www.home-assistant.io/components/
To demonstrate the power of this tool. I’m integrating a twitter account and a text-to-speech module.
Twitter , make it tweet¶
I created a twitter account with the name agrilabIOT_test . You can find the result on https://twitter.com/agrilabiot
I’ve followed https://www.home-assistant.io/components/twitter/ explanation.
You have to create a twitter APP and have the twitter Developper status https://developer.twitter.com/en/apps , at the end of the process you will get your API’s keys (4 of them as described on https://www.home-assistant.io/components/twitter/ )
For obvious reasons, I will not share all my keys on this page.
Then you add those lines in you configuration.yaml file
notify: - name: twitter platform: twitter consumer_key: J***************************X consumer_secret: U***********************************************s access_token: 1*****************************************l access_token_secret: x*******************************************V
Be aware that Home Assistant can takes time to install or update the components you have modify or install in the configuration.yaml file . Sometimes a complete reboot is necessary to update and install some components.
To check that everything is installed correctly, you can go in the web interface service , select the service you have just created notify.twitter and insert some service Data in JSON format like {“message”:”test”}. Click on the CALL SERVICE button, and the tweet should appear on your twitter account.
If you see this message on your twitter account, then the connection is working correctly.
Automation¶
Then I add an automation to tweet certain things depenging on differents criterias.
You can add simple automation throught the web interface.
But you will have more access by editing directly the automations.yaml file
- id: '1557822591613' alias: jour trigger: - below: '800' entity_id: sensor.serial_sensor platform: numeric_state condition: [] action: - data: message: Jour service: notify.twitter - id: '1557822662341' alias: nuit trigger: - above: '910' entity_id: sensor.serial_sensor platform: numeric_state condition: [] action: - data: message: nuit service: notify.twitter
Here, I created 2 automation. One is tweeting “jour” when the serial sensor is below the value 800. The other automation is tweeting “nuit” when the serial sensor is above the value 910.
Twitter rules¶
As twitter as a lot of rules, you can’t tweet the same message. So I can’t just tweet jour or nuit
I modify the message with template.
- id: '1557822591613' alias: jour trigger: - below: '800' entity_id: sensor.serial_sensor platform: numeric_state condition: [] action: - data_template: message: jour {{ states.sensor.serial_sensor.state}} a tel moment {{now()}} service: notify.twitter - id: '1557822662341' alias: nuit trigger: - above: '910' entity_id: sensor.serial_sensor platform: numeric_state condition: [] action: - data_template: message: nuit {{ states.sensor.serial_sensor.state}} a tel moment {{now()}} service: notify.twitter
{{ states.sensor.serial_sensor.state}} will display the value measure by the sensor and {{now()}} will write the time.
You can go to really advance level of templating with condition, random, …
Text-to-speech module¶
I choose to install Pico Text-to-Speech one of the Text-To-Speech module, as described on the https://www.home-assistant.io/components/picotts/ page, you have first to add some software with
sudo apt-get install libttspico-utils
Then you can add the following line in the configuration.yaml file
tts: - platform: picotts language: 'fr-FR'
You have also to give the right access to pusleaudio that will play the sounds.
sudo apt-get install -y vlc-nox apt-utils alsa-utils nano pulseaudio sudo usermod -a -G audio root && \ sudo usermod -a -G pulse-access root sudo amixer cset numid=3 100%
I’ve added the command to set the volume to 100%, on a raspberry pi they are set by default at 40% …
Then you can try a simple test. Go in the Services , select tts.piccotts_say and write {“message”:”Bonjour sa fonctionne”} then press call service and you should hear the message on a speaker connected to the 3.5mm audio jack of your Rapsberry Pi.
If you understand french you will notice that the spelling I used is not correct. picotts does not have advanced function and French is an extremly difficult langage with many rules for pronunciation. Some other language should have better results. I add also some . character to add silence between words.
Then you can play with automation and template.
- id: '1557822591613' alias: jour trigger: - below: '800' entity_id: sensor.serial_sensor platform: numeric_state condition: [] action: - data_template: message: jour {{ states.sensor.serial_sensor.state}} a tel moment {{now()}} service: notify.twitter - data_template: message: a . jour . service: tts.picotts_say - id: '1557822662341' alias: nuit trigger: - above: '910' entity_id: sensor.serial_sensor platform: numeric_state condition: [] action: - data_template: message: nuit {{ states.sensor.serial_sensor.state}} a tel moment {{now()}} service: notify.twitter - data_template: message: a . nuit . service: tts.picotts_say
Now it will speak everytime the conditions change.
You can find plenty of information to program automations on https://www.home-assistant.io/docs/automation/
Why Homeassistant ?¶
The power of Home Assistant comes when you want to combine many differents sensor talking different protocol , using differents platform. At this moment, Home Assistant is in version 0.92 , it has about 1366 components. Some components can control up to 100 differents kind of devices or have many differents kinds of informations.
To mention a few of them, you can send email, sms, play with google agenda, use database, do text to speech, use cameras, control temperature, have some geolocation, do mutlimedia (sound, video, pictures), have weather data … You can use API, MQTT, have interfaces with ZigBee, IrDa, 433Mhz, LoRa, SigFox, X10, and many proprietary format.
I think it is also a great ressource, because each component is written in python and it’s open source.
The upnp system detect automatically more and more devices like WeMo socket, light, fan switch, some TV or sound system…
More advanced¶
Outside the scope of the fabacademy, I’ve fully automated differents place where I had lived.
- id: parole_entree alias: parole_entree hide_entity: True trigger: platform: mqtt topic: "pi/sensor12/in_01" payload: 1 action: - service: tts.picotts_say data_template: message: > '{{ [". . . . Bonjour . . Bienvenue a la maison .",". . . . Merci de toccuper de moi. . "] |random }}' - service: notify.NOTIFIER_NAME data_template: title: 'Appart entree' message: 'Appart entree {{ states.sensor.flower_1_moisture.state}} et {{ states.sensor.flower_2_moisture.state}} et {{ states.sensor.flower_3_moisture.state}} et {{ states.sensor.flower_4_moisture.state}}' data: images: - /home/homeassistant/.homeassistant/photos/photos.jpg - http://192.168.0.41:90/cam_pic_new.php
This part of the automation say with a text to speech a random sentence from a list to welcome when the front door is open and someone is entering (it detect also when someone is leaving and say other messages). In the same time it sends me an email with the moisture value of several of my plant and in the email it integrate 2 pictures comming from 2 differents cameras.
If you did not guess, it was to welcome a neighbour that has accepted to water my plant during holidays (and was aware and curious about the system);
- id: merci_arrosage alias: merci_arrosage hide_entity: True trigger: - platform: numeric_state entity_id: sensor.flower_2_moisture above: 40 - platform: numeric_state entity_id: sensor.flower_1_moisture above: 40 - platform: numeric_state entity_id: sensor.flower_3_moisture above: 40 - platform: numeric_state entity_id: sensor.flower_4_moisture above: 40 action: - service: tts.picotts_say data: message: ' . . . . . merci de mavoir arrosé . . . javais soif . . .'
This other automation detect the moisture level of some plant and thanks with a text to speech the peopel that have water them.
For those systems I combined some plant sensor in bluetooth, the text to speach directly played by the Rapsberry Pi on a speaker, the door sensor made with an esp8266 communicating in MQTT protocol, the camera were
GUI - Graphic User Interface¶
Apparently, this picture does not officially validate the assignement as describe below
Interface and Application Programming : - Write an application that interfaces with an input and/or output device that you made, comparing as many tool options as possible. Learning outcomes - Interpret and implement design and programming protocols to create a Graphic User Interface (GUI).
I am not sure to understand the criteria but the picture below is not enought GUI or not enought “interpret , implement or program” maybe.
Of course I want to validate this week, so I’ve decided to follow dumbly the academic way to validate wich is to use Processing.
Processing¶
Processing is an easy interface that interpret Java and implement library to do visual stuff. Like Arduino it was built to help artist to create more easily with computers.
It is described by wikipedia as Processing is an open-source graphical library and integrated development environment (IDE) / playground built for the electronic arts, new media art, and visual design communities with the purpose of teaching non-programmers the fundamentals of computer programming in a visual context.
Install it from https://processing.org/download/
You have also to have installed Java, if it was not done before.
I will not detail all the functions of Processing . They are plenty of tutorials on the subject https://processing.org/tutorials/
The code in processing :
PImage[] photo = new PImage[19]; import processing.serial.*; Serial myPort; // Create object from Serial class int val; // Data received from the serial port int counter; void setup() { size( 600, 600 ); //screen size background(0); //black baground smooth(); photo[0] = loadImage( "frame_00_delay-0.13s.jpg" ); photo[1] = loadImage( "frame_01_delay-0.13s.jpg" ); photo[2] = loadImage( "frame_02_delay-0.13s.jpg" ); photo[3] = loadImage( "frame_03_delay-0.13s.jpg" ); photo[4] = loadImage( "frame_04_delay-0.13s.jpg" ); photo[5] = loadImage( "frame_05_delay-0.13s.jpg" ); photo[6] = loadImage( "frame_06_delay-0.13s.jpg" ); photo[7] = loadImage( "frame_07_delay-0.13s.jpg" ); photo[8] = loadImage( "frame_08_delay-0.13s.jpg" ); photo[9] = loadImage( "frame_09_delay-0.13s.jpg" ); photo[10] = loadImage( "frame_10_delay-0.13s.jpg" ); photo[11] = loadImage( "frame_11_delay-0.13s.jpg" ); photo[12] = loadImage( "frame_12_delay-0.13s.jpg" ); photo[13] = loadImage( "frame_13_delay-0.13s.jpg" ); photo[14] = loadImage( "frame_14_delay-0.13s.jpg" ); photo[15] = loadImage( "frame_15_delay-0.13s.jpg" ); photo[16] = loadImage( "frame_16_delay-0.13s.jpg" ); photo[17] = loadImage( "frame_17_delay-0.13s.jpg" ); photo[18] = loadImage( "frame_18_delay-0.13s.jpg" ); String portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600); frameRate( 10 ); counter = 18; } void draw() { if (mousePressed == true) { //if we clicked in the window image( photo[counter], 0, 0 ); counter--; if (counter < 0) counter = 0; if (counter == 0) myPort.write('1'); //send a 1 } else { //otherwise //send a 0 image( photo[counter], 0, 0 ); counter++; if (counter > 18) counter = 18; if (counter == 18) myPort.write('0'); //send a 0 } println(counter); }
When I click on the window, it increase a counter, some pictures are stored in a list and the picture are counted up or down from the list to play an animation of pictures. It also sends a “1” or a “0” to the board to light up the LED.
Files¶
Censored keys for security reasons : configuration.yaml and automations.yaml
visiteurs.pde and the corresponding pictures are stored in visiteurs_pictures.zip