Posts

ESP-IDF for Arduino Users, Tutorials Part 2: Delay

This is the second part of a series of ESP-IDF tutorials that I will complete as I learn stuff. Read part 1. One of the best things about Arduino is the ability to just block for a period with: delay(1000); // hang on a second, buddy It’s also one of the worst things. As soon as you need to do a few things at the same time, you will end up using better systems, like calling millis() or using the elapsedMillis library. Anyway, the IDF has you covered. You can delay, but amazingly it appears that once you multi-task (which you will with Free RTOS), the delay doesn’t block the other tasks from running. My Notes: Read the docs, now or later https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html Delay doesn’t have to block like Arduino. Delay some milliseconds like this: vTaskDelay(pdMS_TO_TICKS(10)); Since vTaskDelay accepts ticks, the pdMS_TO_TICKS macro will convert for you. Help yourself out by adding your own macros if you are lazy. I am lazy. #...

ESP-IDF Tutorial: A proposal for verifying data from embedded devices

I'll soon return to the basic tutorials on the ESP-IDF. This tutorial is a one-off on a topic I find interesting. "How can I validate that data from an embedded device came from that device?" This sounds like a job for public key cryptography. I'm no crypto engineer by any means, but I can certainly use libraries. The ESP IDF ships with mbedtls , which is a surprisingly comprehensive suite of crypto. The library is owned by some people called ARM mbed, so I am guessing you can run it on any ARM. Here's the scheme: Create a public/private key pair (RSA in this example) on the embedded device and store it in memory. In our case in the SPIFFS file system. Send the public key to the server Hash and sign every data packet you will send the server with the private key. Embed the signature as a header in the HTTP request Validate the signature on the server when receiving data The remainder of this post will show you how to do those things. The code is kind of intense i...

ESP-IDF for Arduino Users, Tutorials Part 1: Logging

This is the first part of a series of ESP-IDF tutorials that I will complete as I learn stuff. Consider the following Arduino code: Serial.println(“begining”); I call this the “Arduino debugger”. It’s a joke. Arduino has no debugger — don’t be silly, Ali! It’s not really debugging, it’s logging. How do we do logging on ESP-IDF? Well, it’s remarkably easy. Let’s look at it and then you should read the documentation. My notes The logging macros are in “esp_log.h” #include "esp_log.h" Set the logging level in menuconfig. $ idf.py menuconfig Navigate to: Components -> Log Output -> Default log verbosity Define a TAG, e.g. static const char* TAG = “FruityModule”; Call the log methods ESP_LOGD(TAG, “I am a banana”); Look, printf style is available too ESP_LOGD(TAG, “I am a banana and I am %d years old”, age); Multiple levels of the macros are available ESP_LOGE — error (lowest) ESP_LOGW — warning ESP_LOGI — info ESP_LOGD — debug ESP_LOGV — verbose (highest) Complete exam...

ESP-IDF Tutorials Part 0: Prologue

Introduction I have started to try to learn the ESP-IDF. What will follow is a series of short articles as I learn the individual components of the IDF and how to do things that are easy in Arduino. Why? Arduino has been getting me down for a while. Note: I mean the Arduino development platform — the Arduino SDK. I haven’t used the actual hardware for a while. I have been using it mostly on the esp32. It works mostly fine, but I recently spent hours getting Bluetooth Low Energy to work using the esp32-arduino BLE library. The library is very complete and somewhat engineered to the maximum (and a bit more) degree. The Arduino IDE itself is not a pleasant experience for me. I write my own IDEs. Arduino-cli seems to work fine outside the IDE, but it is heinously slow because it seems to recompile the universe. Config options are hard to set and this general limitation has started to make me feel uncomfortable. This post is the prologue. Read the next part: Part 1 Logging

Building a Haskell web app with Snap: Snap quickstart guide

I'm a Haskell newbie, and it's fun. I thought I'd document my adventures. Starting with my attempt to build a web app. I could have spent months picking a web framework. There are decent comparisons on the web. I picked Snap, because of the name (and perhaps some advice from a geeky friend of mine). I've written web frameworks (in Python) and the intro to Snap caught my eye. All pretty arbitrary reasons, so let's get started. First there is a quickstart guide . Great, who doesn't love quickstart guides? It tells me how to install the framework , though that redirects me to another page, but I don't mind. I would have to have Cabal installed, otherwise it wouldn't work. Instead of just plain: cabal install snap I do: cabal install --user --prefix=$HOME snap Which seems the most convenient way to put things in my ~ tree rather than anywhere on the system. Great it works first time with no dependency issues, conflicts, or compile errors. That...

Keeping tallies in Python

Python's collections module has some of the most consistently useful collection data structures you will need for everyday programming. Here's one I didn't know about: collections.Counter  (Python 2.7 only!) It is designed to keep "tallies" or count instances of something. The example will make it all clear: from collections import Counter cars = Counter() # I see one go past, it is red cars['red'] += 1 # And a green one cars['blue'] += 1 # etc This is pretty much like a defaultdict with an integer value, but it is convenient and neat, with some useful constructors. Don't you think?

Watching a file system directory with inotify and Linux

"Inotify is a Linux kernel subsystem that acts to extend filesystems to notice changes to the filesystem, and report those changes to applications." [Citation Needed] . You can use this service from Python using Twisted to watch a directory and its contents. Twisted is perfect for this as you likely want to be doing a number of other things at the same time, for example, making an HTTP request every time a change is noticed. The code is so monstrously simple, I will just paste it: from twisted.internet import inotify from twisted.python import filepath class FileSystemWatcher(object): def __init__(self, path_to_watch): self.path = path_to_watch def Start(self): notifier = inotify.INotify() notifier.startReading() notifier.watch(filepath.FilePath(self.path), callbacks=[self.OnChange]) def OnChange(self, watch, path, mask): print path, 'changed' # or do something else! if __name__ == '__main__': from tw...

Making two instances behave as the same instance in Python

The use-case is this: # Two instances of the same class x = A() y = A() x in {y: 1} # True So we want to be able to check an instance's presence inside a dict, set, or anything that hashes an instance for a key. You need two things: __hash__ method which returns an integer __eq__ method which tests equality against another instance and returns a boolean __hash__ method returns an integer which is used as the hash. I didn't want to invent a hash method, so instead I used the hash of a tuple, which seems a reasonable hashable type to use, but you could use an integer or string or anything. I wanted the tuple contents to be attributes of the instance, with the added side effect that the instance would pass the test: x is (1, 2) # True Here it is: def __hash__(self): return hash((self.name, self.age, self.location)) That is not enough though, if you implement __hash__ you must also implement __eq__, which is simple enough: def __eq__(self, other): return h...

Calling the Google Drive API and other Google APIs asynchronously with Twisted

You may know that the Google API Python Client is built on httplib2 . This is a reasonable general choice, but the tight coupling is unhelpful in situations where a different HTTP library, or an entirely different approach to network programming should be used. An example of this is Twisted . Aside: I won't be going on about how awesome Twisted is, but let's just take it for granted that it is so awesome that I could not write this application without it. Httplib2 is blocking, and that makes it incompatible with being run inside the Twisted reactor. Fortunately we are only the latest person to have this problem, and a solution exists: twisted.internet.threads.deferToThread api_call = drive.files().list() def on_list(resp):   for item in resp['items']:     print item['title'] d = deferToThread(api_call.execute) d.addCallback(on_list) A blocking call will be called in a thread and will callback on the returned deferred when it is done. I apprec...

Getting the command line arguments in Dart (vm)

Another hidden gem in the Dart library today, can you tell I am trying to write a command line thingy? Reading the command line options is really easy. void main() { Options opts = new Options(); for (String arg in opts.arguments) { print(arg); } } Let us play: $ dart opts.dart a a $ dart opts.dart a b c d a b c d Nothing to add, I think, except check the source . Comments on Google+ .

OAuth2.0 with Dart in a web browser

Image
I was trying to access a Google GData API using Dart in a browser. More for fun than profit, but it posed a few challenges, so I thought I should document them. The first step was to Authorize using OAuth2.0 which is the easiest way of Authorizing an application to use Google APIs. This is pretty trivial using server-side Dart, but I wanted to achieve the entire thing inside a web browser, and so this involves a different OAuth2.0 flow to the web-server flow that I am used to using, in this case the OAuth2.0 Client-side Application Flow . The main difference with the web-server flow is that the entire OAuth2.0 dance occurs in a single step, i.e., there is no step to exchange a code for a token. This single step is performed by asking for a token in the initial redirect step with a response_type parameter of token . Additionally, the client secret is not passed at any time, because this would not be safe information for the client application to give up to a web browser (sin...