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.
Get names of all WiFi networks configured and active
| Name | Type | Description |
|---|---|---|
| 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.
| Name | Type | Description | |
|---|---|---|---|
| ssid (required) | string | Wifi router name | Any |
| passphrase (required) | string | Password of Wifi router |
Remove all wifi credentials
# 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
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
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 | 1 | 3 | 5 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| Pi Header | 5 | 3 | 21 | 23 | 19 | 24 | 8 | 29 | 10 | 31 | 12 | 35 | 33 |
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]]
| Function | PI2c Hat | Pi Header |
|---|---|---|
| I2c | ||
| SDA | 3 | 3 |
| SCL | 1 | 5 |
| UART | ||
| UART_TX | 12 | 8 |
| UART_RX | 14 | 10 |
| SPI | ||
| SPI_CE0 | 9 | 24 |
| SPI_MOSI | 8 | 19 |
| SPI_MISO | 5 | 21 |
| SPI_CLK | 7 | 23 |
| PWM | ||
| PWM0 | 16 | 12 |
| PWM1 | 18 | 33 |
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.
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
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
You can use the PI2c as a Serial to network device. Note - CTS and RTS are not supported
# Command line example set serial baudrate
curl --request POST http://${REST_SERVER}:82/api/v1/setBaudrate/115200
# 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"))
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.