@Fitch
Para manejar relés vía I²C se suele utiliza un expansor de bus tipo PCF8574.

El módulo de la foto no incorpora relés, pero vale perfectamente para entender cómo se controla este tipo de dispositivos.
El cable I²C del router se enchufa al conector dupont macho de la izquierda. A la derecha hay otro conector dupont hembra al que se podría conectar a su vez un segundo módulo expansor, y a éste un tercero... y así sucesivamente hasta un total de ocho módulos.
Cuando se conecta más de un módulo a mismo bus, hay que asignar una dirección física distinta a cada uno de ellos. Esto se consigue modificando la posición de los tres jumpers de color naranja.
En la parte superior hay un conector amarillo. El pin de más a la izquierda es 0V. El resto son 8 salidas digitales que pueden tomar los valores 0 o +5V, en función los valores binarios 0 o 1 que les asignemos.
Las 8 salidas digitales se pueden controlar desde una consola de OpenWRT o desde un script. Para establecer el valor de las salidas se usa el comando "i2cset" y para conocer su estado previo "i2cget".
Para entender lo que sigue ahora, hay que estar un poco familiarizado con los sistemas de numeración binario, hexadecimal y su aritmética.
Supongamos que queremos poner la patilla P7 de la tarjeta expansora a +5V y el resto a 0V. Bastará con enviar a la placa el valor binario 0b10000000. El problema es que los scripts no trabajan con binarios. Sólo se puede utilizar decimal y hexadecimal. Sabiendo que el valor decimal 0b10000000 equivale al valor hexadecimal 0x80 y suponiendo que el módulo estuviera conectado en la dirección 0x27 del bus 0, el código a enviar será
i2cset -y 0 0x27 0x80
Si lo que queremos en realidad es activar una o más patillas dejando invariable el resto, no queda otra que tirar del operador binario OR. Primero habría que conocer el estado previo de todas las patillas, luego habría que calcular el valor a enviar y por último enviarlo.
Lo vemos con un ejemplo: activar P7 preservando el estado de las demás salidas. Sabiendo que 0x10000000 equivale a 0x80,
prevState=$((i2cget -y 0 0x27)) # lectura del estado actual
newState=$(($prevState | 0x80)) #cálculo del nuevo valor respetando el estado previo
i2cset -y 0 0x27 $newState # escritura del nuevo estado
Como esto se está poniendo un poco tocho lo dejo ya. Si de verdad interesa, podemos ver cómo desactivar determinadas patillas, respetando los valores previos, en una próxima entrega.