Oxoscript turns into NanoPy - more infos

Network functions

clearRequestHeaders

  clearRequestHeaders()

Deletes all previously added HTTP headers.

addRequestHeader

  addRequestHeader(key:byte[], value:byte[])

Adds an HTTP header to subsequent requests.

Example:

addRequestHeader("Content-Type", "application/json")
addRequestHeader("Content-Length", strLen(body))
addRequestHeader("Authorization", "Bearer " + apiKey)

getMQTTData

  getMQTTData()->byte[1024]

Once the hasMQTTMessage() function has detected that an MQTT message has been received, this function can be used to read out the received data.

if hasMQTTMessage():
    data = getMQTTData()

Limitations: - A maximum of 1024 bytes can be read. Longer data will be appended to a new message without topic.

getMQTTTopic

  getMQTTTopic()->byte[48]

Once the hasMQTTMessage() function has detected that an MQTT message has been received, this function can be used to read the received topic.

if hasMQTTMessage():
    topic = getMQTTTopic()

hasMQTTMessage

  hasMQTTMessage()->bool

Returns true if an MQTT message was received.

Received data can then be read with the following functions:

getMQTTTopic()
getMQTTData()

unsubscribeMQTT

  unsubscribeMQTT(topic:byte[])->int

For this function, the card must be connected to the Internet and an MQTT broker.

Unsubscribes the previously subscribed topic.
The function returns msgId in case of success or -1 in case of error.

subscribeMQTT

  subscribeMQTT(topic:byte[])->int

For this function, the card must be connected to the Internet and an MQTT broker.

Subscribes to the defined topic to receive published messages.
The function returns msgId in case of success or -1 in case of error.

Received messages can then be read with the following functions:

hasMQTTMessage()
getMQTTTopic()
getMQTTData()

Example:

uri = "mqtt://broker.hivemq.com"
username = ""
password = ""

if connectMQTT(uri, username, password):
    subscribeMQTT("myTopic")

def onDraw():
    if hasMQTTMessage():
        print(getMQTTTopic())
        print(getMQTTData())
    delay(100)

publishMQTT

  publishMQTT(topic:byte[], data:byte[])->int

For this function, the card must be connected to the Internet and an MQTT broker.

Publishes a message (data) under the defined topic.
The function returns a msgId in case of success, 0 if QoS = 0 or -1 in case of failure.

Example:

uri = "mqtt://broker.hivemq.com"
username = ""
password = ""

if connectMQTT(uri, username, password):
    publishMQTT("myTopic", "myData")

disconnectMQTT

  disconnectMQTT()

For this function, the card must be connected to the Internet and an MQTT broker.

Disconnects the connection to a MQTT broker.

connectMQTT

  connectMQTT(uri:byte[], username:byte[], password:byte[])->bool

For this function, the card must be connected to the Internet.

Connects the Oxocard to an MQTT broker. The function returns true if the connection was successful.

Username and password can be empty if no authentication is needed.

Example:

# Public MQTT broker (unsecure): https://www.mqtt-dashboard.com/
uri = "mqtt://broker.hivemq.com"
username = ""
password = ""

# Personal MQTT broker (secure): https://console.hivemq.cloud
# uri = "mqtts://abc.s2.eu.hivemq.cloud:8883"
# username = "myUsername"
# password = "myPassword123"

subscribeTopic = "myTopic" # publishTopic = "myTopic
publishTopic = "myTopic"
publishData = "myData string"

title = "MQTT MSG"
drawText(120-textWidth(title)/2, 5, title)
update()

if connectMQTT(uri, username, password):
    subscribeMQTT(subscribeTopic)
else:
    drawText(10, 55, "connect failed!")
    update()

def onDraw():
    if hasMQTTMessage():
        clear()
        textFont(FONT_ROBOTO_32)
        drawText(120-textWidth(title)/2, 5, title)
        topic = getMQTTopic()
        textFont(FONT_ROBOTO_32)
        drawText(10, 55, "topic:")
        textFont(FONT_ROBOTO_24)
        drawText(20, 95, topic)
        data = getMQTTData()
        textFont(FONT_ROBOTO_32)
        drawText(10, 150, "data:")
        textFont(FONT_ROBOTO_24)
        drawText(20, 190, data)
        update()
    buttonByte = getButton()
    if buttonByte > 0:
        publishMQTT(publishTopic, publishData)
        if buttonByte == 4:
            if returnToMenu():
                return
        while getButton(): delay(10)
    delay(100)

Note: At the beginning of the URI the protocol must be defined: “mqtt://…” or “mqtts://…”. If necessary, a port can also be appended to the host (“…:8883”).

selectCertificate

  selectCertificate(path:byte[])

With this function an own certificate (.pem) can be selected in the file system of the Oxocard.

This is only necessary if the certificate could not be requested automatically and stored in the “certs” folder of the Oxocard.

Example:

selectCertificate("certs/nanopy-io.pem")

Note: The own certificate (.pem) must be stored beforehand e.g. via file browser in the file system of the Oxocard.

MQTT introduction

MQTT stands for Message Queuing Telemetry Transport. The protocol consists of rules that define how IoT devices can publish and subscribe to data over the Internet. The protocol connects devices using the (pub/sub) pattern. The sender (publisher) and the receiver (subscriber) communicate via so-called topics and are decoupled from each other. The connection between them is managed by an MQTT server (“broker”).

In the following example, the Oxocard subscribes and publishes to the same topic and can thus receive its own messages (via MQTT broker).
The free public server of HiveMQ is used as broker.

Example:

# Public MQTT broker (unsecure): https://www.mqtt-dashboard.com/
uri = "mqtt://broker.hivemq.com"
username = ""
password = ""

subscribeTopic = "myTopic"
publishTopic = "myTopic"
publishData = "myData string"

title = "MQTT MSG"
drawText(120-textWidth(title)/2, 5, title)
update()

if connectMQTT(uri, username, password):
    subscribeMQTT(subscribeTopic)
else:
    drawText(10, 55, "connect failed!")
    update()

def onDraw():
    if hasMQTTMessage():
        clear()
        textFont(FONT_ROBOTO_32)
        drawText(120-textWidth(title)/2, 5, title)
        topic = getMQTTopic()
        textFont(FONT_ROBOTO_32)
        drawText(10, 55, "topic:")
        textFont(FONT_ROBOTO_24)
        drawText(20, 95, topic)
        data = getMQTTData()
        textFont(FONT_ROBOTO_32)
        drawText(10, 150, "data:")
        textFont(FONT_ROBOTO_24)
        drawText(20, 190, data)
        update()
    buttonByte = getButton()
    if buttonByte > 0:
        publishMQTT(publishTopic, publishData)
        if buttonByte == 4:
            if returnToMenu():
                return
        while getButton(): delay(10)
    delay(100)

HTTP/HTTPS introduction

The Hypertext Transfer Protocol (HTTP) has been developed to enable communication between clients and servers.
HTTP Secure (HTTPS) is the secure version of the HTTP protocol.

The Oxocard supports the two most commonly used HTTP methods: GET and POST.

GET example:

# Request and display IP
url = "http://httpbin.org/ip"
if (getRequest(url)):
    origin = readRequestJSON("origin")
    drawText(10, 10, origin)
else:
    drawText(10, 10, "error")
update()

POST example:

# Post simple JSON
url = "https://httpbin.org/post"
body = "{\"field1\":\"value1\"}"
print("sending POST request...")
if (postRequest(url, body)):
    print("ok")
else:
    print("error")

Network introduction

If the Oxocard is connected to the Internet, it can communicate with the world using the network functions.

At the moment, it supports simple HTTP/HTTPS requests and MQTT/MQTTS.

The server certificate required for secure protocols (https & mqtts) is first checked in the internal CA store and then searched for in the Oxocard’s file system in the “certs” folder. If it is not available, it is requested from the target server via our server (openssl). Alternatively, you can also add a certificate yourself and refer to it with the selectCertificate() function.

postRequest

  postRequest(url:byte[], body:byte[])->bool

The card must be connected to the Internet for this function.

Sends a POST request to the defined URL.
The function returns true if the request was successful (200 OK).

Any server responses can then be read using the following functions:

readRequestLength()
readRequest(offset)
readRequestJSON(jsonPath)

Example:

# Toggle Shelly relay
url = "http://192.168.42.146/relay/0"
body = "turn=toggle"
def onDraw():
    if getButton():
        postRequest(url, body)
        while(getButton()): delay(50)
    delay(50)

readRequestJSON

  readRequestJSON(jsonPath:byte[])->byte[128]

Returns the content of a JSON response as text (max. 128 bytes) of the request previously requested with getRequest().

With jsonPath the key to be read can be defined.
With ‘.’ or ‘/’ also nested JSON objects can be selected.

Example1:

url = "http://api.nanopy.io/v1/utc"
getRequest(url) # {"utc":1667912328}
drawText(10, 10, readRequestJSON("utc"))
update()

Example2:

# {
#   "myObj": {
#     "mySubObj": {
#       "myArray": [
#         {"myKey":111},
#         {"myKey":222},
#         {"myKey":333}
#       ],
#     }
#   }
# }
readRequestJSON("myObj.mySubObj.myArray.0.myKey") # "111"
readRequestJSON("myObj/mySubObj/myArray/2/myKey") # "333"

Note:
readRequestJSON() always returns a string (byte[]). The stringTo…() functions can then be used to convert the result to the appropriate data type.

readRequest

  readRequest(offset:int)->byte[128]

Returns the text (max. 128 bytes) of the request previously requested with getRequest().

With offset the start position can be defined, which determines from where the response should be read.
This allows to read longer responses in several steps.

Example:

url = "http://api.nanopy.io/v1/hello_world"
getRequest(url)
drawText(10, 10, readRequest(0))
drawText(10, 50, readRequest(6))
update()

Note:
If you use your own server and want to return plain text, you must also define the ‘Content-Length’ in the header.

readRequestLength

  readRequestLength()->int

Returns the length (in bytes) of the request previously requested with getRequest().

getRequest

  getRequest(url:byte[])->bool

For this function, the card must be connected to the Internet.

Sends a GET request to the defined URL.
The function returns true if the request was successful (200 OK).

The requested data can then be read with the following functions:

readRequestLength()
readRequest(offset)
readRequestJSON(jsonPath)

Example:

url = "http://api.nanopy.io/v1/utc"
if (getRequest(url)):
    utc = readRequestJSON("utc")
    drawText(10, 10, stringToInt(utc))
else:
    drawText(10, 10, "error")
update()

Limitations: - A maximum of 32k bytes can be requested. Longer responses will be truncated