Getting Started

Example

REST API details

Nothing beats a quick example

async function run() {
  try {
    const MCP9808_I2CADDR_DEFAULT        = 0x18
    const MCP9808_REG_MANUF_ID             = 0x06
    const meta = new Map();
    const user = 'none';
    const password = 'none';
    const deviceHost = 'GO-1234567.local'; //or ip address if your OS does not support this
    meta.set('Authorization', 'Basic ' + Buffer.from(`${user}:${password}`).toString('base64'));
    meta.set('Content-Type', 'application/json');
    const headers = new Headers(meta);
    const instructions = [
      {
        func: 'i2cBegin',
      }, {
        func: 'i2cSetSlaveAddress',
        arg1: MCP9808_I2CADDR_DEFAULT
      }, {
        func: 'i2cSetBaudRate',
        arg1: 100000
      }, {
        func: 'i2cWrite',
        arg1: Buffer.from([MCP9808_REG_MANUF_ID]).toString('base64')
      }, {
        func: 'i2cRead',
        arg1: 2
      }
    ];
    //Setup device for i2c and get Manufacturer id of device
    let resp = await fetch(`http://${deviceHost}/api/v1/instr/exec`,
      { method: 'POST', body: JSON.stringify(instructions), headers });
    if(!resp.ok) {
      const respText = await resp.text();
      console.log(`Error processing instructions. Response ${respText}`);
      process.exit(2);
    }
    let jsonResp = await resp.json();
    if(jsonResp.success == false) {
      console.debug(`Error communicating with response\n${JSON.stringify(jsonResp, undefined, 2)}`);
    } else {
      console.debug(`Success communicating with response\n${JSON.stringify(jsonResp, undefined, 2)}`);
      console.log(`Manufacturer id is ${Buffer.from(jsonResp.instructions[4].returnValue, 'base64').toString('ascii')}`)
    }
    //Clean up and end i2c comm
    resp = await fetch(`http://${deviceHost}/api/v1/instr/exec`, { method: 'POST', body:
      JSON.stringify([{
        func: 'i2cEnd'
      }]),
      headers
    });
    if(!resp.ok) {
      console.log(`Error processing instructions`);
      process.exit(3);
    }
  } catch(error) {
    console.log(`Unknown error. Message - ${error.message}`);
  }
}

In this javascript example we are communicating with a MCP9808 I2c temperature sensor. The Instructions and InstructionsResponse schemes in the API has greater detail on the structure and properties. You can chain instructions and POST them to /api/v1/instr/exec. Instructions which return data can find the value in the InstructionsResponse. Specifically the property returnValue at the corresponding instruction index of the response. Binary data is not valid in REST so it needs to be converted to and from base64 strings.


Configuring WiFi for PI2c OS

▶ 200 - Response is an object with two keys 'all' and 'active'.

application/json
NameTypeDescription
all (required)array(string)all configured WiFi network names (max 1)
active (required)array(string)network names which are active
  • Add WiFi connection credentials. This will delete existing WiFi connections and corresponding credentials. This is useful to give the device short term internet access for updates and/or control the device while on the same wireless network.

    POST http://REST_SERVER:63333/wifi/add

Request body

application/json
NameTypeDescription
ssid (required)stringWifi router nameAny
passphrase (required)stringPassword of Wifi router

Examples

  # Command line example adding WiFi credentials
  curl --header "Content-Type: application/json" --request POST
  --data '{"ssid":"userSSID","passphrase": "myPassphrase"}' http://${REST_SERVER}:63333/wifi/add

  # Command line example remove all WiFi credentials
  curl --header "Content-Type: application/json" --request POST http://${REST_SERVER}:63333/wifi/remove

PI2c OS Device Discovery

Each PI2c can be reached via a Bonjour/Zeroconf address. For example GO-1234567.local, where 1234567 is the PI2c ID. On some operating systems the .local is not required. If this does not work for Windows you can Download and install Bonjour Print Services for Windows v2.0.2

On a MAC run the following command and look for devices prefixed with GO-

dns-sd -B _ssh 

On a linux with avahi-browse installed run the following command and look for devices prefixed with GO-

avahi-browse -rac

Pinout & Wiring


PI2c software uses the pin numbers corresponding with the PI2c hat. If you are not using the hat and are connecting straight to the Pi you can use the following chart to help with the mapping. These are the physical pin numbers . The software allows the i2c, spi, and pwm pins to also act as gpio.


PI2C Hat 13578912131415161718
Pi Header53212319248291031123533
const map = [[1, 5], [3, 3], [5, 21], [7, 23], [8, 19], [9, 24], [12, 8], 
[13, 29], [14, 10], [15, 31], [16, 12], [17, 35], [18, 33]]
FunctionPI2c HatPi Header
I2c
SDA33
SCL15
UART
UART_TX128
UART_RX1410
SPI
SPI_CE0924
SPI_MOSI819
SPI_MISO521
SPI_CLK723
PWM
PWM01612
PWM11833

PI2c Hat

Connectors

SW 3V3/5V

The PI2c hat has a switch to output either no output, 3.3v, or 5v to pins 4 and 6. The amount of current is limited by the power supply of the device.

Red & Green Led

The PI2c hat has two leds you can control. One red and one green. The red led will blink once the device is fully running on startup. It can be used as needed afterwards.

API Instruction led


Saving named instruction sets

To save from having to send many instructions frequently you can store them as a named set on the device and execute later.

  #Command line example get all stored instruction set names
  curl --header "Content-Type: application/json" --request GET http://${REST_SERVER}/api/v1/instr/stored

  #Command line example post new stored instruction set with special name initialize
  #initialize will be run everytime PI2c starts up
  curl --header "Content-Type: application/json"   --request POST
  --data '[{"func":"mode","arg1": 11, "arg2":"OUTPUT"}]' http://${REST_SERVER}/api/v1/instr/stored/initialize

Serial TCP/Websockets

You can use the PI2c as a Serial to network device. Note - CTS and RTS are not supported

  1. Wire your device to the PI2c using the info above
  2. Configure the Serial baudrate with via the Rest api
# Command line example set serial baudrate
curl --request POST http://${REST_SERVER}:82/api/v1/setBaudrate/115200
  1. Using your desired platform connect to Websocket port 1337 for or TCP port 47070. Traffic over serial will be routed to these sockets.
# Python TCP write serial example
import socket
class SerialSocket:
  def __init__(self, sock=None):
    if sock is None:
      self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    else:
      self.sock = sock

  def connect(self, host, port):
    self.sock.connect((host, port))

  def write(self, msg):
    totalsent = 0
    MSGLEN = len(msg)
    while totalsent < MSGLEN:
      sent = self.sock.send(msg[totalsent:])
      if sent == 0:
        raise RuntimeError("socket connection broken")
      totalsent = totalsent + sent

  def read(self, num):
    chunks = []
    bytes_recd = 0
    MSGLEN = num
    while bytes_recd < MSGLEN:
      chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
      if chunk == b'':
        raise RuntimeError("socket connection broken")
      chunks.append(chunk)
      bytes_recd = bytes_recd + len(chunk)
    return b''.join(chunks)

serial = SerialSocket()
serial.connect('GO-XXXXXXX', 47070)
serial.write(bytearray("hello\n", "utf-8"))

Security/Updates

PI2c will generally be plugged directly in to your computer so there is no chance of someone getting remote access. If you give it WiFi access to your network it will still be protected from the outside, unless you forwarded the ports, which is not recommended. You can give the device a password to limit who can control it on your network. See

  # Command line example sending new settings
  curl --header "Content-Type: application/json" --request POST
  --data '{
   "name": "Some name",
   "webURL": "www.your-domain.com/locationOfYourCustomWebApplication",
   "password": "Some password"
  }' http://${REST_SERVER}/api/v1/settings/general

The password can be ignored if you are directly plugged in. It is recommended to occasionally put the device on your WiFi network so that it can auto update.

If there is an update it should take no longer than three minutes to complete the automatic process, and should only occur when the board is powered. Afterwards, you can remove the device from your network if you prefer. You can confirm completion by making a GET request to /api/v1/version and confirming the version has changed.