diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9068464 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +all: deploy + +build: + pxt build + +deploy: + pxt deploy + +test: + pxt test diff --git a/README.md b/README.md index 3bff09f..36460f9 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,76 @@ # pxt-wifi -MakeCode extension for WiFi:bit. Connect micro:bit to Internet through WiFi network. +MakeCode extension for [WiFi:bit](https://e-radionica.com/en/wifi-bit.html): +
+![alt text](icon.png "WiFi:bit") +
+It's used for connecting to the Internet or local network through WiFi connection. You can send or receive information by using HTTP methods or AT commands. WiFi:bit can also be used as breakout board (edge connector). +
+## Commands +### Connect to WiFi:bit +![alt text](/images/01%20-%20connectToWiFiBit.png "connectToWiFiBit()") +
+Makes a serial connection between micro:bit and WiFi:bit. You should put it in a start block of every WiFi:bit project. +
+### Connect to WiFi network +![alt text](/images/02%20-%20connectToWiFiNetwork.png "connectToWiFiNetwork()") +
+Connects WiFi:bit to WiFi network. You should execute it only once. Next time WiFi:bit will connect automatically. +
+### Disconnect from WiFi network +![alt text](/images/03%20-%20disconnectFromWifiNetwork.png "disconnectFromWifiNetwork()") +
+Disconnects WiFi:bit from WiFi network. You need this command only if you're paranoid. :) +
+### Execute AT command +![alt text](/images/04%20-%20executeAtCommand.png "executeAtCommand()") +
+Executes AT command. It's for power users, for total control or cases which can't be covered with other commands. [List of AT commands.](https://room-15.github.io/blog/2015/03/26/esp8266-at-command-reference/) +
+### Execute HTTP method +![alt text](/images/05%20-%20executeHttpMethod.png "executeHttpMethod()") +
+Main command of this extension. It's used for data sending, changing, deleting and fetching by using some of the [HTTP methods](https://www.tutorialspoint.com/http/http_methods.htm). This is basic form of command. You can expand it with optional parameters (body and headers). +
+### Blynk: write pin value +![alt text](/images/06%20-%20writePinValue.png "writePinValue()") +
+Write Blynk pin value. [Blynk](https://blynk.io/) is popular IoT service. This command simplifies its usage with WiFi:bit projects. +
+### Blynk: read pin value +![alt text](/images/07%20-%20readPinValue.png "readPinValue()") +
+Read Blynk pin value. [Blynk](https://blynk.io/) is popular IoT service. This command simplifies its usage with WiFi:bit projects. +
+### Newline +![alt text](/images/08%20-%20newline.png "newline()") +
+Line separator. It's used in multiline body and headers. You should put it between each pair of lines. +
+### Change HTTP method wait period +![alt text](/images/09%20-%20changeHttpMethodWaitPeriod.png "changeHttpMethodWaitPeriod()") +
+Changes HTTP method wait period. It's for power users and available only in JavaScript part of MakeCode. By defaut HTTP method execution time is cca. 15 seconds. That's OK for almost all networks. If you have good network you can reduce execution time. Default input value is 1000. If you, for example, set it to 500 execution will be twice faster. You can also slow execution by setting a value which is greater than 1000. +
+## Examples +### Connect to the Internet +![alt text](/images/example1.png "Connect to the Internet") +
+### Send dice value to ThingSpeak +![alt text](/images/example2.png "Send dice value to ThingSpeak") +
+### Send some data to Beebotte +![alt text](/images/example3.png "Send some data to Beebotte") +
+### Read and write Blynk pin values +![alt text](/images/example4.png "Read and write Blynk pin values") +
+For explanation of examples and more details, check [official tutorial](https://e-radionica.com/en/blog/using-wifibit-with-the-official-makecode-extension-pxt-wifibit/). +
+
+## License +MIT License +
+
+## Supported targets + +* for PXT/microbit diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..8e9b809 Binary files /dev/null and b/icon.png differ diff --git a/images/01 - connectToWiFiBit.png b/images/01 - connectToWiFiBit.png new file mode 100644 index 0000000..28269ec Binary files /dev/null and b/images/01 - connectToWiFiBit.png differ diff --git a/images/02 - connectToWiFiNetwork.png b/images/02 - connectToWiFiNetwork.png new file mode 100644 index 0000000..10cda6f Binary files /dev/null and b/images/02 - connectToWiFiNetwork.png differ diff --git a/images/03 - disconnectFromWifiNetwork.png b/images/03 - disconnectFromWifiNetwork.png new file mode 100644 index 0000000..dd66e32 Binary files /dev/null and b/images/03 - disconnectFromWifiNetwork.png differ diff --git a/images/04 - executeAtCommand.png b/images/04 - executeAtCommand.png new file mode 100644 index 0000000..fb38e2b Binary files /dev/null and b/images/04 - executeAtCommand.png differ diff --git a/images/05 - executeHttpMethod.png b/images/05 - executeHttpMethod.png new file mode 100644 index 0000000..4cb8383 Binary files /dev/null and b/images/05 - executeHttpMethod.png differ diff --git a/images/06 - writePinValue.png b/images/06 - writePinValue.png new file mode 100644 index 0000000..4c1f962 Binary files /dev/null and b/images/06 - writePinValue.png differ diff --git a/images/07 - readPinValue.png b/images/07 - readPinValue.png new file mode 100644 index 0000000..a5ec488 Binary files /dev/null and b/images/07 - readPinValue.png differ diff --git a/images/08 - newline.png b/images/08 - newline.png new file mode 100644 index 0000000..b711207 Binary files /dev/null and b/images/08 - newline.png differ diff --git a/images/09 - changeHttpMethodWaitPeriod.png b/images/09 - changeHttpMethodWaitPeriod.png new file mode 100644 index 0000000..c7ccd2f Binary files /dev/null and b/images/09 - changeHttpMethodWaitPeriod.png differ diff --git a/images/example1.png b/images/example1.png new file mode 100644 index 0000000..1bad0b4 Binary files /dev/null and b/images/example1.png differ diff --git a/images/example2.png b/images/example2.png new file mode 100644 index 0000000..a3d31e2 Binary files /dev/null and b/images/example2.png differ diff --git a/images/example3.png b/images/example3.png new file mode 100644 index 0000000..6e94645 Binary files /dev/null and b/images/example3.png differ diff --git a/images/example4.png b/images/example4.png new file mode 100644 index 0000000..0a71344 Binary files /dev/null and b/images/example4.png differ diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..f24a51b --- /dev/null +++ b/main.ts @@ -0,0 +1,189 @@ +enum HttpMethod { + GET, + POST, + PUT, + HEAD, + DELETE, + PATCH, + OPTIONS, + CONNECT, + TRACE +} + +enum Newline { + CRLF, + LF, + CR +} + + +/** + * WiFi:bit commands. + */ +//% color=#3452C3 weight=90 icon="\uf1eb" block="WiFi:bit" +namespace WiFiBit { + + function writeToSerial(data: string, waitTime: number): void { + serial.writeString(data + "\u000D" + "\u000A") + if (waitTime > 0) { + basic.pause(waitTime) + } + } + + let pauseBaseValue: number = 1000 + + /** + * Change HTTP method wait period. + * @param newPauseBaseValue Base value, eg: 1000 + */ + //% weight=1 + export function changeHttpMethodWaitPeriod(newPauseBaseValue: number): void { + pauseBaseValue = newPauseBaseValue + } + + /** + * Make a serial connection between micro:bit and WiFi:bit. + */ + //% weight=100 + //% blockId="wfb_connect" block="connect to WiFi:bit" + export function connectToWiFiBit(): void { + serial.redirect( + SerialPin.P16, + SerialPin.P8, + BaudRate.BaudRate115200 + ) + basic.pause(100) + // Restart module: + writeToSerial("AT+RST", 2000) + // WIFI mode = Station mode (client): + writeToSerial("AT+CWMODE=1", 5000) + } + + /** + * Connect to WiFi network. + * @param ssid SSID, eg: "SSID" + * @param key Key, eg: "key" + */ + //% weight=99 + //% blockId="wfb_wifi_on" block="connect to WiFi network %ssid, %key" + export function connectToWiFiNetwork(ssid: string, key: string): void { + // Connect to AP: + writeToSerial("AT+CWJAP=\"" + ssid + "\",\"" + key + "\"", 6000) + } + + /** + * Disconnect from WiFi network. + */ + //% weight=98 + //% blockId="wfb_wifi_off" block="disconnect from WiFi network" + export function disconnectFromWiFiNetwork(): void { + // Disconnect from AP: + writeToSerial("AT+CWQAP", 6000) + } + + /** + * Execute AT command. + * @param command AT command, eg: "AT" + * @param waitTime Wait time after execution, eg: 1000 + */ + //% weight=97 + //% blockId="wfb_at" block="execute AT command %command and then wait %waitTime ms" + export function executeAtCommand(command: string, waitTime: number): void { + writeToSerial(command, waitTime) + } + + /** + * Execute HTTP method. + * @param method HTTP method, eg: HttpMethod.GET + * @param host Host, eg: "google.com" + * @param port Port, eg: 80 + * @param urlPath Path, eg: "/search?q=something" + * @param headers Headers + * @param body Body + */ + //% weight=96 + //% blockId="wfb_http" block="execute HTTP method %method|host: %host|port: %port|path: %urlPath||headers: %headers|body: %body" + export function executeHttpMethod(method: HttpMethod, host: string, port: number, urlPath: string, headers?: string, body?: string): void { + let myMethod: string + switch (method) { + case HttpMethod.GET: myMethod = "GET"; break; + case HttpMethod.POST: myMethod = "POST"; break; + case HttpMethod.PUT: myMethod = "PUT"; break; + case HttpMethod.HEAD: myMethod = "HEAD"; break; + case HttpMethod.DELETE: myMethod = "DELETE"; break; + case HttpMethod.PATCH: myMethod = "PATCH"; break; + case HttpMethod.OPTIONS: myMethod = "OPTIONS"; break; + case HttpMethod.CONNECT: myMethod = "CONNECT"; break; + case HttpMethod.TRACE: myMethod = "TRACE"; + } + // Establish TCP connection: + let data: string = "AT+CIPSTART=\"TCP\",\"" + host + "\"," + port + writeToSerial(data, pauseBaseValue * 6) + data = myMethod + " " + urlPath + " HTTP/1.1" + "\u000D" + "\u000A" + + "Host: " + host + "\u000D" + "\u000A" + if (headers && headers.length > 0) { + data += headers + "\u000D" + "\u000A" + } + if (data && data.length > 0) { + data += "\u000D" + "\u000A" + body + "\u000D" + "\u000A" + } + data += "\u000D" + "\u000A" + // Send data: + writeToSerial("AT+CIPSEND=" + (data.length + 2), pauseBaseValue * 3) + writeToSerial(data, pauseBaseValue * 6) + // Close TCP connection: + writeToSerial("AT+CIPCLOSE", pauseBaseValue * 3) + } + + /** + * Write Blynk pin value. + * @param value Value, eg: "510" + * @param pin Pin, eg: "A0" + * @param auth_token Token, eg: "14dabda3551b4dd5ab46464af582f7d2" + */ + //% weight=95 + //% blockId="wfb_blynk_write" block="Blynk: write %value to %pin, token is %auth_token" + export function writePinValue(value: string, pin: string, auth_token: string): void { + executeHttpMethod( + HttpMethod.GET, + "blynk-cloud.com", + 80, + "/" + auth_token + "/update/" + pin + "?value=" + value + ) + } + + /** + * Read Blynk pin value. + * @param pin Pin, eg: "A0" + * @param auth_token Token, eg: "14dabda3551b4dd5ab46464af582f7d2" + */ + //% weight=94 + //% blockId="wfb_blynk_read" block="Blynk: read %pin, token is %auth_token" + export function readPinValue(pin: string, auth_token: string): string { + executeAtCommand("ATE0", 1000) + let response: string + serial.onDataReceived(serial.delimiters(Delimiters.NewLine), function () { + response += serial.readString() + }) + executeHttpMethod( + HttpMethod.GET, + "blynk-cloud.com", + 80, + "/" + auth_token + "/get/" + pin + ) + let value: string = response.substr(response.indexOf("[") + 2, response.indexOf("]") - response.indexOf("[") - 3) + response = null + serial.onDataReceived(serial.delimiters(Delimiters.NewLine), () => { }) + return value + } + + /** + * Line separator. It's used when headers or body are multiline. + */ + //% weight=93 + //% blockId="wfb_crlf" block="CRLF" + export function newline(): string { + return "\u000D" + "\u000A" + } + +} diff --git a/pxt.json b/pxt.json new file mode 100644 index 0000000..33ba1a4 --- /dev/null +++ b/pxt.json @@ -0,0 +1,16 @@ +{ + "name": "pxt-wifi", + "version": "1.0.0", + "description": "Connect micro:bit to the Internet with a WiFi:bit module.", + "dependencies": { + "core": "*" + }, + "files": [ + "README.md", + "main.ts" + ], + "testFiles": [ + "test.ts" + ], + "public": true +} diff --git a/test.ts b/test.ts new file mode 100644 index 0000000..34fc63d --- /dev/null +++ b/test.ts @@ -0,0 +1 @@ +// tests go here; this will not be compiled when this package is used as a library diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a2079ff --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "target": "es5", + "noImplicitAny": true, + "outDir": "built", + "rootDir": "." + }, + "exclude": ["pxt_modules/**/*test.ts"] +}