Skip to content
This repository has been archived by the owner on Jul 14, 2023. It is now read-only.

Commit

Permalink
mxchip: iotc api
Browse files Browse the repository at this point in the history
  • Loading branch information
obastemur committed Dec 18, 2018
1 parent be024f9 commit 6bf727a
Show file tree
Hide file tree
Showing 15 changed files with 1,342 additions and 736 deletions.
3 changes: 3 additions & 0 deletions AZ3166/build_firmware/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ that along with the example, please follow the steps below;
Clone `devkit-sdk` into this folder.
```
git clone https://github.com/Microsoft/devkit-sdk
cd devkit-sdk
git checkout 0ca1b6ed8d06e7a2b371eb2c4e54ff61d6e3e899
cd ..
```

Install [iotz](https://github.com/azure/iotz). You will need `Docker` and `node.js` (8+) is installed on your machine.
Expand Down
58 changes: 23 additions & 35 deletions AZ3166/inc/iotHubClient.h → AZ3166/inc/AzureIOTClient.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

#ifndef IOT_HUB_CLIENT_H
#define IOT_HUB_CLIENT_H
#ifndef AZURE_IOT_CLIENT_H
#define AZURE_IOT_CLIENT_H

typedef int (*hubDesiredCallback)(const char *, size_t, char **response, size_t* resp_size);
typedef void (*hubMethodCallback)(const char *, size_t);
typedef int (*hubMethodCallback)(const char *, size_t);

#include <AzureIotHub.h>

typedef struct CALLBACK_LOOKUP_TAG_D {
char* name;
hubDesiredCallback callback;
} CALLBACK_LOOKUP_D;
#include "iotc.h"

typedef struct CALLBACK_LOOKUP_TAG_M {
char* name;
Expand All @@ -32,49 +27,42 @@ struct DirectMethodNode

DirectMethodNode *next;
DirectMethodNode():
methodName(NULL), payload(NULL), next(NULL), length(0) { }
methodName(NULL), payload(NULL), length(0), next(NULL) { }
DirectMethodNode(char *m, char *p, size_t s):
methodName(m), payload(p), next(NULL), length(s) { }
methodName(m), payload(p), length(s), next(NULL) { }
};

class IoTHubClient
class AzureIOTClient
{
IOTContext context;

bool hasError;
char deviceId[IOT_CENTRAL_MAX_LEN];
char hubName[IOT_CENTRAL_MAX_LEN];
int displayCharPos;
int waitCount;
bool needsCopying;
char displayHubName[AZ3166_DISPLAY_MAX_COLUMN + 1];
IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;
int trackingId;
char *deviceId;

DirectMethodNode *rootNode, *lastNode;

void initIotHubClient();
void closeIotHubClient();
void init();
void close();

public:
IoTHubClient(): hasError(false), displayCharPos(0),
waitCount(3), needsCopying(true),
iotHubClientHandle(NULL), trackingId(0), rootNode(NULL),
lastNode(NULL), methodCallbackCount(0),
AzureIOTClient(): context(NULL), hasError(false), displayCharPos(0),
rootNode(NULL), lastNode(NULL), methodCallbackCount(0),
desiredCallbackCount(0), needsReconnect(false)
{
memset(deviceId, 0, IOT_CENTRAL_MAX_LEN);
memset(hubName, 0, IOT_CENTRAL_MAX_LEN);
initIotHubClient();
init();
}

~IoTHubClient()
~AzureIOTClient()
{
closeIotHubClient();
close();
}

void hubClientYield(void) {
checkConnection();

IoTHubClient_LL_DoWork(iotHubClientHandle);
iotc_do_work(context);
ThreadAPI_Sleep(1 /* waitTime */);
}

Expand Down Expand Up @@ -130,8 +118,8 @@ class IoTHubClient
if (needsReconnect) {
// simple reconnection of the client in the event of a disconnect
LOG_VERBOSE("Reconnecting to the IoT Hub");
closeIotHubClient();
initIotHubClient();
close();
init();

needsReconnect = false;
}
Expand All @@ -141,15 +129,15 @@ class IoTHubClient
bool sendReportedProperty(const char *payload);

bool registerMethod(const char *methodName, hubMethodCallback callback);
bool registerDesiredProperty(const char *propertyName, hubDesiredCallback callback);
bool registerDesiredProperty(const char *propertyName, hubMethodCallback callback);

void displayDeviceInfo(); // TODO: should this go under device?

int methodCallbackCount;
int desiredCallbackCount;
CALLBACK_LOOKUP_M methodCallbackList[MAX_CALLBACK_COUNT];
CALLBACK_LOOKUP_D desiredCallbackList[MAX_CALLBACK_COUNT];
CALLBACK_LOOKUP_M desiredCallbackList[MAX_CALLBACK_COUNT];
bool needsReconnect;
};

#endif /* IOT_HUB_CLIENT_H */
#endif /* AZURE_IOT_CLIENT_H */
2 changes: 1 addition & 1 deletion AZ3166/inc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ConfigController {
static void readWiFi(char* ssid, int ssidLen, char *password, int passwordLen);
static void readConnectionString(char * connectionString, uint32_t buffer_size);
static void readIotCentralConfig(char * iotCentralConfig, uint32_t buffer_size);
static void readGroupSXKeyAndDeviceId(char * scopeId, char * registrationId, char * sas, bool &sasKey);
static void readGroupSXKeyAndDeviceId(char * scopeId, char * registrationId, char * sas, char &atype);

static void clearWiFiEEPROM();
static void clearAzureEEPROM();
Expand Down
3 changes: 1 addition & 2 deletions AZ3166/inc/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ class LoopController;
#define EMPTY_JSON "{}"
struct Globals
{
static const char * completedString; // "completed"
static WiFiController wiFiController;
static SensorController sensorController;
static LoopController * loopController;
Expand All @@ -76,7 +75,7 @@ struct Globals
#define IOT_CENTRAL_ZONE_IDX 0x02
#define IOT_CENTRAL_MAX_LEN STRING_BUFFER_128
#define AZIOTC_FW_MAJOR_VERSION 2
#define AZIOTC_FW_MINOR_VERSION 0
#define AZIOTC_FW_MINOR_VERSION 1
#define AZIOTC_FW_PATCH_VERSION 0
#define AZIOTC_FW_VERSION TO_STRING(AZIOTC_FW_MAJOR_VERSION AZIOTC_FW_MINOR_VERSION AZIOTC_FW_PATCH_VERSION) "-MSIOTC"

Expand Down
32 changes: 29 additions & 3 deletions AZ3166/inc/httpHtmlData.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ charset=utf-8\r\nCache-Control: no-cache, no-store, \
must-revalidate\r\n\r\n"

#define HTTP_HEADER_HTML HTTP_HEADER_NO_CACHE "\r\n<!DOCTYPE html><html lang=\"en\"><head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\"> <title>Azure IoT Central Device Config</title> <style>@charset \"UTF-8\"; /*Flavor name: Default (mini-default)Author: Angelos Chalaris (chalarangelo@gmail.com)Maintainers: Angelos Chalarismini.css version: v2.1.5 (Fermion)*/ /*Browsers resets and base typography.*/ html{font-size: 16px;}html, *{font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Droid Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif; line-height: 1.5; -webkit-text-size-adjust: 100%;}*{font-size: 1rem;}body{margin: 0; color: #212121; background: #f8f8f8;}section{display: block;}input{overflow: visible;}h1, h2{line-height: 1.2em; margin: 0.75rem 0.5rem; font-weight: 500;}h2 small{color: #424242; display: block; margin-top: -0.25rem;}h1{font-size: 2rem;}h2{font-size: 1.6875rem;}p{margin: 0.5rem;}small{font-size: 0.75em;}a{color: #0277bd; text-decoration: underline; opacity: 1; transition: opacity 0.3s;}a:visited{color: #01579b;}a:hover, a:focus{opacity: 0.75;}/*Definitions for the grid system.*/ .container{margin: 0 auto; padding: 0 0.75rem;}.row{box-sizing: border-box; display: -webkit-box; -webkit-box-flex: 0; -webkit-box-orient: horizontal; -webkit-box-direction: normal; display: -webkit-flex; display: flex; -webkit-flex: 0 1 auto; flex: 0 1 auto; -webkit-flex-flow: row wrap; flex-flow: row wrap;}[class^='col-sm-']{box-sizing: border-box; -webkit-box-flex: 0; -webkit-flex: 0 0 auto; flex: 0 0 auto; padding: 0 0.25rem;}.col-sm-10{max-width: 83.33333%; -webkit-flex-basis: 83.33333%; flex-basis: 83.33333%;}.col-sm-offset-1{margin-left: 8.33333%;}@media screen and (min-width: 768px){.col-md-4{max-width: 33.33333%; -webkit-flex-basis: 33.33333%; flex-basis: 33.33333%;}.col-md-offset-4{margin-left: 33.33333%;}}/*Definitions for navigation elements.*/ header{display: block; height: 2.75rem; background: #1e6bb8; color: #f5f5f5; padding: 0.125rem 0.5rem; white-space: nowrap; overflow-x: auto; overflow-y: hidden;}header .logo{color: #f5f5f5; font-size: 1.35rem; line-height: 1.8125em; margin: 0.0625rem 0.375rem 0.0625rem 0.0625rem; transition: opacity 0.3s;}header .logo{text-decoration: none;}/*Definitions for forms and input elements.*/ form{background: #eeeeee; border: 1px solid #c9c9c9; margin: 0.5rem; padding: 0.75rem 0.5rem 1.125rem;}.input-group{display: inline-block;}.input-group.fluid{display: -webkit-box; -webkit-box-pack: justify; display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; -webkit-justify-content: center; justify-content: center;}.input-group.fluid>input{-webkit-box-flex: 1; max-width: 100%; -webkit-flex-grow: 1; flex-grow: 1; -webkit-flex-basis: 0; flex-basis: 0;}@media screen and (max-width: 767px){.input-group.fluid{-webkit-box-orient: vertical; -webkit-align-items: stretch; align-items: stretch; -webkit-flex-direction: column; flex-direction: column;}}[type=\"password\"], select{box-sizing: border-box; background: #fafafa; color: #212121; border: 1px solid #c9c9c9; border-radius: 2px; margin: 0.25rem; padding: 0.5rem 0.75rem;}[type=\"text\"], select{box-sizing: border-box; background: #fafafa; color: #212121; border: 1px solid #c9c9c9; border-radius: 2px; margin: 0.25rem; padding: 0.5rem 0.75rem;}fieldset.group{margin: 0; padding: 0; margin-bottom: 0.25em; margin-top: 0.5em; padding-bottom: 1.125em; padding-top: 0.5em; border: 1px solid #696666;}fieldset.group legend{margin: 0; padding: 0; margin-left: 15px; color: #696666; font-size: 1rem;}ul.checkbox{margin: 0; padding: 0; margin-left: 60px; list-style: none;}ul.checkbox li input{margin-right: .25em;}ul.checkbox li{border: 1px transparent solid; display:inline-block; width:12em;}ul.checkbox li label{margin-left: 5px;}input:not([type=\"button\"]):not([type=\"submit\"]):not([type=\"reset\"]):hover, input:not([type=\"button\"]):not([type=\"submit\"]):not([type=\"reset\"]):focus, select:hover, select:focus{border-color: #0288d1; box-shadow: none;}input:not([type=\"button\"]):not([type=\"submit\"]):not([type=\"reset\"]):disabled, select:disabled{cursor: not-allowed; opacity: 0.75;}::-webkit-input-placeholder{opacity: 1; color: #616161;}::-moz-placeholder{opacity: 1; color: #616161;}::-ms-placeholder{opacity: 1; color: #616161;}::placeholder{opacity: 1; color: #616161;}button::-moz-focus-inner, [type=\"submit\"]::-moz-focus-inner{border-style: none; padding: 0;}button, [type=\"submit\"]{-webkit-appearance: button;}button{overflow: visible; text-transform: none;}button, [type=\"submit\"], a.button, .button{display: inline-block; background: rgba(208, 208, 208, 0.75); color: #212121; border: 0; border-radius: 2px; padding: 0.5rem 0.75rem; margin: 0.5rem; text-decoration: none; transition: background 0.3s; cursor: pointer;}button:hover, button:focus, [type=\"submit\"]:hover, [type=\"submit\"]:focus, a.button:hover, a.button:focus, .button:hover, .button:focus{background: #d0d0d0; opacity: 1;}button:disabled, [type=\"submit\"]:disabled, a.button:disabled, .button:disabled{cursor: not-allowed; opacity: 0.75;}/*Custom elements for forms and input elements.*/ button.primary, [type=\"submit\"].primary, .button.primary{background: rgba(30, 107, 184, 0.9); color: #fafafa;}button.primary:hover, button.primary:focus, [type=\"submit\"].primary:hover, [type=\"submit\"].primary:focus, .button.primary:hover, .button.primary:focus{background: #0277bd;}#content{margin-top: 2em;}</style></head>"
#define HTTP_START_PAGE_HTML_ HTTP_HEADER_HTML "<body> <header> <h1 class=\"logo\">Azure IoT Central Device Config</h1> </header> <section class=\"container\"> <div id=\"content\" class=\"row\"> <div class=\"col-sm-10 col-sm-offset-1 col-md-4 col-md-offset-4\" style=\"text-align:center;\"><form action=\"/PROCESS\" method=\"get\">\
#define HTTP_START_PAGE_HTML_ HTTP_HEADER_HTML "<body> <header> <h1 class=\"logo\">Azure IoT Central Device Config</h1> </header>\
<section class=\"container\"> <div id=\"content\" class=\"row\"> <div class=\"col-sm-10 col-sm-offset-1 col-md-4 col-md-offset-4\" \
style=\"text-align:center;\"><form action=\"/PROCESS\" method=\"get\" id=\"frm\">\
<div class=\"input-group fluid\"> <select name=\"SSID\" id=\"SSID\" style=\"width:100%;\" required>{{networks}}</select> </div>\
<div class=\"input-group fluid\"> <input type=\"password\" value=\"\" name=\"PASS\" id=\"password\" title=\"WiFi Password\" placeholder=\"WiFi Password\" style=\"width:100%;\"> </div>\
<div class=\"input-group fluid\"> <input type=\"password\" value=\"\" name=\"PINCO\" id=\"PINCO\" title=\"Device Pin Code\" placeholder=\"Device Pin Code\" style=\"width:100%;\"> </div>\
<div class=\"input-group fluid\"> <input type=\"text\" value=\"\" name=\"SCOPEID\" id=\"SCOPEID\" title=\"Scope Id\" placeholder=\"Scope Id\" style=\"width:100%;\"> </div>\
<div class=\"input-group fluid\"> <input type=\"text\" value=\"\" name=\"REGID\" id=\"REGID\" title=\"Device Id\" placeholder=\"Device Id\" style=\"width:100%;\"> </div>\
<div class=\"input-group fluid\"> <select name=\"AUTH\" id=\"AUTH\" style=\"width:100%;\" \
required><option value=\"S\">SAS Key</option><option value=\"X\">X509 Certificate</option></select></div>\
required><option value=\"S\">SAS Key</option><option value=\"X\">X509 Certificate</option><option value=\"C\">Connection string</option></select></div>\
<div class=\"input-group fluid\"> <span id=\"link\" style=\"display:none;font-size:80%\"> \
Setting the scope id is enough to authenticate with x509 option. \
This sample firmware already has the client cert builtin. Use \
Expand All @@ -42,15 +44,39 @@ class=\"primary\">Configure Device</button> </div></form> <h5>Click \
refresh the page if you do not see your network</h5> </div></div></section>\
<script>\
var sel = document.getElementById('AUTH');\
var r = document.getElementById('REGID');\
var s = document.getElementById('SASKEY');\
document.getElementById('frm').onsubmit = function(e) {\
if (sel.selectedIndex == 2) {\
str = s.value.toLowerCase(); ind = str.indexOf('deviceid');\
ind2 = str.indexOf(';', ind + 1); if (ind2 == -1) ind2 = str.length;\
str = s.value.substr(ind + 9, ind2 - (ind + 9));\
r.value = str;\
}\
};\
sel.onchange = function(e) {\
var s = document.getElementById('SASKEY');\
var cid = document.getElementById('SCOPEID');\
var r = document.getElementById('REGID');\
var l = document.getElementById('link');\
if (sel.selectedIndex == 1) {\
s.style='display:none'; r.value = 'riot-device-cert'; r.disabled = true;\
l.style='';\
} else {\
cid.style='';\
r.style='';\
} \
else if (sel.selectedIndex == 2) {\
s.title='Connection String'; \
s.placeholder='Connection String';\
cid.style='display:none';\
r.style='display:none';\
} \
else {\
l.style='display:none';\
cid.style='';\
r.style='';\
s.title = 'Primary/Secondary device key'; \
s.placeholder = 'Primary/Secondary device key'; \
s.style = ''; r.value=''; r.disabled = undefined;\
}\
}\
Expand Down
146 changes: 146 additions & 0 deletions AZ3166/inc/iotc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

#ifndef AZURE_IOTC_API
#define AZURE_IOTC_API

// ***** Type definitions *****
typedef struct HTTP_PROXY_OPTIONS_TAG
{
const char* host_address;
int port;
const char* username;
const char* password;
} HTTP_PROXY_OPTIONS;

typedef struct IOTCallbackInfo_TAG {
const char* eventName;
const char* tag;
const char* payload;
unsigned payload_length;

void *appContext;

int statusCode;
void *callbackResponse;
} IOTCallbackInfo;

typedef void* IOTContext;

// ***** Macro definitions *****
#define IOTC_PROTOCOL_MQTT 0x01
#define IOTC_PROTOCOL_AMQP 0x02
#define IOTC_PROTOCOL_HTTP 0x04
typedef short IOTProtocol;

#define IOTC_LOGGING_DISABLED 0x01
#define IOTC_LOGGING_API_ONLY 0x02
#define IOTC_LOGGING_ALL 0x10
typedef short IOTLogLevel;

#define IOTC_CONNECT_SYMM_KEY 0x01
#define IOTC_CONNECT_X509_CERT 0x02
#define IOTC_CONNECT_CONNECTION_STRING 0x04
typedef short IOTConnectType;

#define IOTC_CONNECTION_EXPIRED_SAS_TOKEN 0x01
#define IOTC_CONNECTION_DEVICE_DISABLED 0x02
#define IOTC_CONNECTION_BAD_CREDENTIAL 0x04
#define IOTC_CONNECTION_RETRY_EXPIRED 0x08
#define IOTC_CONNECTION_NO_NETWORK 0x10
#define IOTC_CONNECTION_COMMUNICATION_ERROR 0x20
#define IOTC_CONNECTION_OK 0x40
typedef short IOTConnectionState;

#define IOTC_MESSAGE_ACCEPTED 0x01
#define IOTC_MESSAGE_REJECTED 0x02
#define IOTC_MESSAGE_ABANDONED 0x04
typedef short IOTMessageStatus;

// ***** API *****
// Set the level of logging (see the options above)
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_set_logging(IOTLogLevel level);

// Initialize the device context. The context variable will be used by rest of the API
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_init_context(IOTContext *ctx);

// Free device context.
// Call this after `init_context`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_free_context(IOTContext ctx);

// Connect to Azure IoT Central
// Call this after `init_context`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_connect(IOTContext ctx, const char* scope, const char* keyORcert,
const char* device_id, IOTConnectType type);

// Disconnect
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_disconnect(IOTContext ctx);

// If your endpoint is different than the default AzureIoTCentral endpoint, set it
// using this API.
// Call this before `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_set_global_endpoint(IOTContext ctx, const char* endpoint_uri);

// Set the connection protocol (MQTT is default)
// Call this before `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_set_protocol(IOTContext ctx, IOTProtocol protocol);

// Set the custom certificates for custom endpoints
// Call this before `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_set_trusted_certs(IOTContext ctx, const char* certs);

// Set the proxy settings
// Call this before `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_set_proxy(IOTContext ctx, HTTP_PROXY_OPTIONS proxy);

// Sends a telemetry payload (JSON)
// Call this after `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_send_telemetry(IOTContext ctx, const char* payload, unsigned length, void *appContext);

// Sends a state payload (JSON)
// Call this after `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_send_state (IOTContext ctx, const char* payload, unsigned length, void *appContext);

// Sends an event payload (JSON)
// Call this after `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_send_event (IOTContext ctx, const char* payload, unsigned length, void *appContext);

// Sends a property payload (JSON)
// Call this after `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_send_property (IOTContext ctx, const char* payload, unsigned length, void *appContext);

/*
eventName:
ConnectionStatus
MessageSent
MessageReceived
Command
SettingsUpdated
Error
*/
typedef void (*IOTCallback)(IOTContext ctx, IOTCallbackInfo &callbackInfo);

// Register to one of the events listed above
// Call this after `init_context`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_on(IOTContext ctx, const char* eventName, IOTCallback callback, void *appContext);

// Lets SDK to do background work
// Call this after `connect`
// returns 0 if there is no error. Otherwise, error code will be returned.
int iotc_do_work(IOTContext ctx);

#endif // AZURE_IOTC_API
Loading

0 comments on commit 6bf727a

Please sign in to comment.