Ad-Hoc Connection

You can simply use the iwconfig tools on the both your Pis to join to an ad-hoc network.

use the following:

sudo iwconfig wlan0 mode ad-hoc channel 01 essid my-net

You can use your Link-Local addresses to interact with the pis in general.

A smart way to know your local network Pis can be to use:

ping -I wlan0 224.0.0.1

It is a Multicast Address which will give your pings from the Pis which have the same ad-hoc parameters.

This should most definitely give you the 169.254.x.x address of the Pi within the ad-hoc network.

Networking upon next boot

In best case use the following in your (both Pis) /etc/rc.local file:

sudo nano /etc/rc.local

iwconfig wlan0 mode ad-hoc essid my-net channel 01
exit 0

and add brcmfmac in to your /etc/modules file for availability of chipset on boot.

For further help I have a GitHub repository which can set up Pis (any model 2 or 3) in Ad-Hoc mode with IPv6 Link Local Addresses.

Cálculo exponencial

Cálculo exponencial usando python:

import sys
#Calculate the exponential 

def iterPower(base, exp):
    '''
    base: int or float.
    exp: int >= 0
 
    returns: int or float, base^exp
    '''
    index=0
    resultado=base
    if base==1 or exp==0:
        return 1
    if base ==0:
        return 0
    for index in (range(exp-1)):
        resultado=resultado*base
    return resultado

def main():
    try:
        print(iterPower(int(sys.argv[1]),int(sys.argv[2])))
    except:
        print ("Faltan argumentos\nUsar como base_exp.py [base] [exponente] ")
    
if __name__ == '__main__':
    main()

Electricidad

Tarifaluzhora

Pagina de precios de electricidad

https://tarifaluzhora.es/

REE

Obtener los datos del coste de la electricidad. Información de como gestionar los datos API.

https://www.ree.es/es/apidatos

1.4 Example requests

Below are listed a few example requests combining several query parameters:

Requesting the daily balance widget for January (default geo_limit; Spanish): https://apidatos.ree.es/es/datos/balance/balance-electrico?start_date=2019-01-01T00:00&end_date=2019-01-31T22:00&time_trunc=day Requesting the monthly general IRE widget for the year 2018 (peninsular geo_limit; English): https://apidatos.ree.es/en/datos/demanda/ire-general?start_date=2018-01-01T00:00&end_date=2018-12-31T23:59&time_trunc=month&geo_trunc=electric_system&geo_limit=peninsular&geo_ids=8741 Requesting the yearly generation structure widget between 2014 and 2018 (ccaa geo_limit; Castilla la Mancha; Spanish): https://apidatos.ree.es/es/datos/generacion/estructura-generacion?start_date=2014-01-01T00:00&end_date=2018-12-31T23:59&time_trunc=year&geo_trunc=electric_system&geo_limit=ccaa&geo_ids=7

Lectura Corriente

Luego ya sería adquirir tantos sensores no intrusivos como necesitemos: SCT-013-000.

Run app at startup

Editing rc.local

On your Pi, edit the file /etc/rc.local using the editor of your choice. You must edit it with root permissions:

sudo nano /etc/rc.local

Add commands to execute the python program, preferably using absolute referencing of the file location (complete file path are preferred). Be sure to leave the line exit 0 at the end, then save the file and exit. In nano, to exit, type Ctrl-x, and then Y.

Edit RC Local File Configure Run a Program On Your Raspberry Pi At Startup

If your program runs continuously (runs an infinite loop) or is likely not to exit, you must be sure to fork the process by adding an ampersand (“&”) to the end of the command, like:

sudo python -u /full/path/main.py /dev/null 2>&1 &

The Pi will run this program at bootup, and before other services are started.  If you don’t include the ampersand and if your program runs continuously, the Pi will not complete its boot process. The ampersand allows the command to run in a separate process and continue booting with the main process running.

Now reboot the Pi to test it:

sudo reboot

Temperature on a Raspberry Pi

The below example guides you through how to plot your CPU temp as a graph to an image file, the code is in my github repository where I’ll hopefully add further functionality in the future.

How to guide

First off you need to install Python3

sudo apt-get install python3
sudo apt-get install python-setuptools
sudo apt-get install python3-pip

Next install GNUPlot

sudo apt-get install gnuplot-x11

Then we need to setup a working directory:

cd ~
mkdir plottemp
cd plottemp

create the necessary files:

nano datagen.py

Paste in the following code:

#!/usr/bin/env python

import sys, os, logging, urllib, datetime

def fetchtemp():
	cmd = '/opt/vc/bin/vcgencmd measure_temp'
	line = os.popen(cmd).readline().strip()
	output = line.split('=')[1].split("'")[0]#+' C'
	return output 

format = "%Y-%m-%d,%H:%M:%S" 
today = datetime.datetime.today()
s = today.strftime(format)
output = s+' '+fetchtemp()+'\n'

print(output)

with open('/home/pi/plottemp/tempdata.dat', 'a') as f:
	f.write(output)

Create this also

nano plottemp.sh

and paste the following:

#!/bin/bash
echo "set terminal png size 900, 300
set xdata time
set xrange [ time(0) - 86400 : time(0) ]    # 86400 sec = 1 day
set timefmt '%Y-%m-%d,%H:%M:%S'
set format x '%H:%M'
set output '/home/pi/plottemp/tempplot.png'
plot '/home/pi/plottemp/tempdata.dat' using 1:2 with lines" | gnuplot

make it executable

chmod +x plottemp.sh

next all we have to do is to run the script every 5 minutes (or whatever interval you choose) with cron:

crontab -e

and add this line:

*/5 * * * * python3 /home/pi/plottemp/datagen.py && /home/pi/plottemp/plottemp.sh &> /dev/null

and there we have it, it will generate a file called:

plottemp.png

The result

If you have successfully implemented the instructions you should get something like this:

How it works

I’ll very briefly walk you through how it works – there’s a cron job running every five minutes which firstly runs a command line function which reports the CPU temp and saves it to a log file. Upon completion it then runs a GNUPlot command to generate a graph of the last 24 hours logging.

Download

Install from GitHub:

https://github.com/sduro/temperatura.git

ISS Tracker

Introducción.

Pagina donde se obtine la latitud y longitud de la estacion espacial https://api.wheretheiss.at/v1/satellites/25544

{«name»:»iss»,»id»:25544,»latitude»:-49.286361096358,»longitude»:-79.112974058659,»altitude»:435.51955173138,»velocity»:27541.325742835,»visibility»:»daylight»,»footprint»:4585.5919346302,»timestamp»:1609618348,»daynum»:2459217.3419907,»solar_lat»:-22.833735560553,»solar_lon»:237.96509928192,»units»:»kilometers»}

Fuente: https://wheretheiss.at/w/developer

ISSTracker (Version 1)

Having researched trackers there are lots of sites that provide handy APIs to get the current latitude and longitude of the space station.  I settled on using wheretheissis.at as this provided the most comprehensive information I could find in an API.

All the coded needed to do was pull down the JSON provided by the API then parse the data for the values it needed. Below is an extract to show you how this is done

#!/usr/bin/env python3

from urllib.request import urlopen
import json
import time

feed_url="https://api.wheretheiss.at/v1/satellites/25544"

def informacion():
    try:
        jsonFeed = urlopen(feed_url)
        feedData = jsonFeed.read()
        #print feedData
        jsonFeed.close()
        data = json.loads(feedData)
        return data
    except Exception:
        import traceback
        print ("generic exception: " + traceback.format_exc())
 
    return []       
 
#use this method to retrieve from web API
def parseISSDataFeed():
    data = informacion()
    if len(data) == 0:
        return []

    name = data['name']
    lat = data['latitude']
    lng = data['longitude']
    alt = data['altitude']

    return [name, lng, lat, alt]

def main():
        print (parseISSDataFeed())

if __name__ == "__main__":
    while(1):
        time.sleep(1)
        main()


Now to display the ISS.  The visible globe is essentially half of a sphere and so represents 180º in both the latitude (top/bottom or North/South) and longitude (left/right or East/West).  With only 8 pixels that means each LED represents 22.5º of the Earths’ surface.

To display the location of the ISS we take the current lat/long of its position over the Earth and map that to the pixel/LED it falls into.  That’s all well and good when it’s on the “visible” side of the globe in the overlay, but what to do when it goes “behind” our overlay?

Rather than make the ISS “disappear” I opted to still display it but in a different colour so it can be tracked as it reappears on the visible side of our globe.  So now the LED lights up yellow for the visible side of the globe and blue when the ISS passes over the horizon to the rear of the planet.

Menu bash en Linux

Using dialog, the command would look like this:

dialog --clear --backtitle "Backtitle here" --title "Title here" --menu "Choose one of the following options:" 15 40 4 \
1 "Option 1" \
2 "Option 2" \
3 "Option 3"
enter image description here

Putting it in a script:

#!/bin/bash

HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"

OPTIONS=(1 "Option 1"
         2 "Option 2"
         3 "Option 3")

CHOICE=$(dialog --clear \
                --backtitle "$BACKTITLE" \
                --title "$TITLE" \
                --menu "$MENU" \
                $HEIGHT $WIDTH $CHOICE_HEIGHT \
                "${OPTIONS[@]}" \
                2>&1 >/dev/tty)

clear
case $CHOICE in
        1)
            echo "You chose Option 1"
            ;;
        2)
            echo "You chose Option 2"
            ;;
        3)
            echo "You chose Option 3"
            ;;
esac

Cliente y Servidor TCP/IP

Introducción

Los conectores se pueden configurar para que actúen como un servidor y escuchen mensajes entrantes, o se conecten a otras aplicaciones como un cliente. Después de que ambos extremos de un conector TCP/IP estén conectados, la comunicación es bidireccional.

Servidor de eco

Este programa de ejemplo, basado en la documentación de la biblioteca estándar, recibe los mensajes entrantes y los devuelve al remitente. Comienza creando un conector TCP/IP, luego bind() se utiliza para asociar el conector con la dirección del servidor. En este caso, la dirección es localhost, refiriéndose al servidor actual, y número de puerto es 10000.socket_echo_server.py

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to the port
server_address = ('localhost', 10000)
print('starting up on {} port {}'.format(*server_address))
sock.bind(server_address)

# Listen for incoming connections
sock.listen(1)

while True:
    # Wait for a connection
    print('waiting for a connection')
    connection, client_address = sock.accept()
    try:
        print('connection from', client_address)

        # Receive the data in small chunks and retransmit it
        while True:
            data = connection.recv(16)
            print('received {!r}'.format(data))
            if data:
                print('sending data back to the client')
                connection.sendall(data)
            else:
                print('no data from', client_address)
                break

    finally:
        # Clean up the connection
        connection.close()

Al llamar a listen() pone al conector en modo servidor, y accept() espera una conexión entrante. El argumento entero es el número de conexiones que el sistema debe hacer cola en segundo plano antes de rechazar nuevos clientes. Este ejemplo solo espera trabajar con una conexión a la vez.

accept() devuelve una conexión abierta entre el servidor y cliente, junto con la dirección del cliente. La conexión es en realidad un conector diferente en otro puerto (asignado por el núcleo). Los datos se leen de la conexión con recv() y se transmiten con sendall().

Cuando finaliza la comunicación con un cliente, la conexión debe ser limpiada usando close(). Este ejemplo usa un bloque try:finally para asegurar que close() siempre se llame, incluso en caso de error.

Cliente de eco

El programa cliente configura su socket de forma diferente a como lo hace un servidor. En lugar de unirse a un puerto y escuchar, usa connect() para conectar el conector directamente a la dirección de control remoto.socket_echo_client.py

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('localhost', 10000)
print('connecting to {} port {}'.format(*server_address))
sock.connect(server_address)

try:

    # Send data
    message = b'This is the message.  It will be repeated.'
    print('sending {!r}'.format(message))
    sock.sendall(message)

    # Look for the response
    amount_received = 0
    amount_expected = len(message)

    while amount_received < amount_expected:
        data = sock.recv(16)
        amount_received += len(data)
        print('received {!r}'.format(data))

finally:
    print('closing socket')
    sock.close()

Una vez establecida la conexión, los datos pueden ser enviados a través del socket con sendall() y recibidos con recv(), al igual que en el servidor. Cuando se envía todo el mensaje y se recibe una copia, el conector es cerrado para liberar el puerto.

Cliente y servidor juntos

El cliente y el servidor deben ejecutarse en ventanas de terminal separadas, para que puedan comunicarse entre ellos. La salida del servidor muestra la conexión y datos entrantes, así como la respuesta enviada al cliente.

$ python3 socket_echo_server.py
starting up on localhost port 10000
waiting for a connection
connection from ('127.0.0.1', 65141)
received b'This is the mess'
sending data back to the client
received b'age.  It will be'
sending data back to the client
received b' repeated.'
sending data back to the client
received b''
no data from ('127.0.0.1', 65141)
waiting for a connection

La salida del cliente muestra el mensaje saliente y la respuesta del servidor.

$ python3 socket_echo_client.py
connecting to localhost port 10000
sending b'This is the message.  It will be repeated.'
received b'This is the mess'
received b'age.  It will be'
received b' repeated.'
closing socket

Conexiones de cliente fáciles

Los clientes TCP/IP pueden ahorrar algunos pasos utilizando la función de conveniencia create_connection() para conectarse a un servidor. La función toma un argumento, una tupla de dos valores que contiene la dirección del servidor, y deduce la mejor dirección para usar para la conexión.socket_echo_client_easy.py

import socket
import sys


def get_constants(prefix):
    """Create a dictionary mapping socket module
    constants to their names.
    """
    return {
        getattr(socket, n): n
        for n in dir(socket)
        if n.startswith(prefix)
    }


families = get_constants('AF_')
types = get_constants('SOCK_')
protocols = get_constants('IPPROTO_')

# Create a TCP/IP socket
sock = socket.create_connection(('localhost', 10000))

print('Family  :', families[sock.family])
print('Type    :', types[sock.type])
print('Protocol:', protocols[sock.proto])
print()

try:

    # Send data
    message = b'This is the message.  It will be repeated.'
    print('sending {!r}'.format(message))
    sock.sendall(message)

    amount_received = 0
    amount_expected = len(message)

    while amount_received < amount_expected:
        data = sock.recv(16)
        amount_received += len(data)
        print('received {!r}'.format(data))

finally:
    print('closing socket')
    sock.close()

create_connection() usa getaddrinfo() para encontrar candidatos para los parámetros de conexión, y devuelve un socket abierto con el primera configuración que crea una conexión exitosa. Los atributos familytype, y proto pueden ser examinados para determinar el tipo de socket que se devuelve.

$ python3 socket_echo_client_easy.py
Family  : AF_INET
Type    : SOCK_STREAM
Protocol: IPPROTO_TCP

sending b'This is the message.  It will be repeated.'
received b'This is the mess'
received b'age.  It will be'
received b' repeated.'
closing socket

Elegir una dirección para escuchar

Es importante vincular un servidor a la dirección correcta, para que los clientes pueden comunicarse con él. Los ejemplos anteriores todos usaron 'localhost' como la dirección IP, que limita las conexiones a los clientes ejecutándose en el mismo servidor. Utiliza una dirección pública del servidor, como el valor devuelto por gethostname(), para permitir que otros hosts se conecten. Este ejemplo modifica el servidor de eco para escuchar en una dirección especificada a través de un argumento de línea de comando.socket_echo_server_explicit.py

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to the address given on the command line
server_name = sys.argv[1]
server_address = (server_name, 10000)
print('starting up on {} port {}'.format(*server_address))
sock.bind(server_address)
sock.listen(1)

while True:
    print('waiting for a connection')
    connection, client_address = sock.accept()
    try:
        print('client connected:', client_address)
        while True:
            data = connection.recv(16)
            print('received {!r}'.format(data))
            if data:
                connection.sendall(data)
            else:
                break
    finally:
        connection.close()

Se necesita una modificación similar al programa cliente antes de que el servidor puede ser probadosocket_echo_client_explicit.py

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port on the server
# given by the caller
server_address = (sys.argv[1], 10000)
print('connecting to {} port {}'.format(*server_address))
sock.connect(server_address)

try:

    message = b'This is the message.  It will be repeated.'
    print('sending {!r}'.format(message))
    sock.sendall(message)

    amount_received = 0
    amount_expected = len(message)
    while amount_received < amount_expected:
        data = sock.recv(16)
        amount_received += len(data)
        print('received {!r}'.format(data))

finally:
    sock.close()

Después de iniciar el servidor con el argumento hubert, el comando netstat lo muestra escuchando en la dirección de host nombrada.

$ host hubert.hellfly.net

hubert.hellfly.net has address 10.9.0.6

$ netstat -an | grep 10000

Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
...
tcp4       0      0  10.9.0.6.10000         *.*                    LISTEN
...

Ejecutar el cliente en otro host, pasando hubert.hellfly.net como host donde se ejecuta el servidor, produce:

$ hostname

apu

$ python3 ./socket_echo_client_explicit.py hubert.hellfly.net
connecting to hubert.hellfly.net port 10000
sending b'This is the message.  It will be repeated.'
received b'This is the mess'
received b'age.  It will be'
received b' repeated.'

Y la salida del servidor es:

$ python3 socket_echo_server_explicit.py hubert.hellfly.net
starting up on hubert.hellfly.net port 10000
waiting for a connection
client connected: ('10.9.0.10', 33139)
received b''
waiting for a connection
client connected: ('10.9.0.10', 33140)
received b'This is the mess'
received b'age.  It will be'
received b' repeated.'
received b''
waiting for a connection

Muchos servidores tienen más de una interfaz de red, y por lo tanto más de una dirección IP. En lugar de ejecutar copias separadas de un servicio enlazada a cada dirección IP, usa la dirección especial INADDR_ANY para escuchar en todas las direcciones al mismo tiempo. Aunque socket define una constante para INADDR_ANY, es un valor entero y debe convertirse en una cadena de dirección en notación de puntos antes de que pueda ser pasada a bind(). Como atajo, usa «0.0.0.0» o una cadena vacía ('') en lugar de hacer la conversión.socket_echo_server_any.py

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to the address given on the command line
server_address = ('', 10000)
sock.bind(server_address)
print('starting up on {} port {}'.format(*sock.getsockname()))
sock.listen(1)

while True:
    print('waiting for a connection')
    connection, client_address = sock.accept()
    try:
        print('client connected:', client_address)
        while True:
            data = connection.recv(16)
            print('received {!r}'.format(data))
            if data:
                connection.sendall(data)
            else:
                break
    finally:
        connection.close()

Para ver la dirección utilizada por un socket, llama a su método getsockname(). Tras iniciar el servicio, ejecutar netstat nuevamente lo muestra escuchando las conexiones entrantes en cualquier dirección.

$ netstat -an

Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address    Foreign Address  (state)
...
tcp4       0      0  *.10000          *.*              LISTEN
...

Cómo instalar una pantalla LCD de 3.5

Instalación

Conecta el LCD a la Raspberry Pi, debe retroiluminarse la pantalla.

Abre un Shell a la raspberry.

Antes de empezar, verifica que tienes conexión a internet y actualiza apt-get:

sudo apt-get update
sudo apt-get upgrade

1 – Borramos por si hubiera restos de alguna instalación anterior:

sudo rm -rf LCD-show

2 – Clonamos repo git en local:

git clone https://github.com/goodtft/LCD-show.git

*Si da un error por no encontrar git lo instalamos con:

sudo apt install git

Y repetimos paso 2.

3 – Damos permisos de ejecución:

sudo chmod -R 755 LCD-show

4 – Entramos en el directorio

cd LCD-show/

Verás que hay muchos drivers, debes seleccionar el específico a tu LCD, ójo, no todos los 3.5 son iguales!.

Lista de dispositivos con su instalador correspondiente:

2.4″ RPi Display(MPI2401) –> sudo ./LCD24-show
2.8″ RPi Display(MPI2801) –> sudo ./LCD28-show
3.2″ RPi Display(MPI3201) –> sudo ./LCD32-show
3.5″ RPi Display(MPI3501) –> sudo ./LCD35-show
3.5″ HDMI Display-B(MPI3508) –> sudo ./MPI3508-show
3.2″ High Speed display(MHS32) -> sudo ./MHS32-show
3.5″ High Speed display(MHS35) -> sudo ./MHS35-show
4.0″ High Speed display(MHS40) -> sudo ./MHS40-show
4.0″ HDMI Display(MPI4008) –> sudo ./MPI4008-show
5.0″ HDMI Display-B(Capacitor touch)(MPI5001) -> sudo ./MPI5001-show
5.0″ HDMI Display(Resistance touch)(MPI5008) -> sudo ./LCD5-show
7.0″ HDMI Display-B-800X480(MPI7001) –>sudo ./LCD7B-show
7.0″ HDMI Display-C-1024X600(MPI7002) -> sudo ./LCD7C-show

Si quieres volver a utilizar la salida HDMI –> sudo ./LCD-hdmi

En mi caso es un 3.5»Raspberry LCD Driver: ILI9486, SKU: MPI3501, así que ejecuto la instalación:

sudo ./LCD35-show

Comenzará a descargar los paquetes necesarios y reiniciará.

Cuando arranque ya tendrás activo tu lcd y verás toda la info por pantalla.

Durante el arranque, la pantalla está unos segundos en blanco, es normal.