2019-11-15 11:57 — By Erik van Eykelen

Yoctopuce Hardware Project

Being fairly busy these days with Releasewise during the day, and often nights and weekends too, I started looking for a small tinkering project to put my mind on something else. Earlier this year I bought a small display and light sensor from Yoctopuce. Time to make some software!

Components

Yocto-MaxiDisplay

The display has 128 x 64 resolution with crisp, green pixels.

Yocto-Light-V3

This sensor is capable of measuring ambient light, returning the measurement in lux. You can actually split the board and move the light sensor chip a few meters away from the remaining (largest) part of the board (requires soldering 4 wires).

Goals

I set some modest goals:

  • Display the pathetically small number of Twitter followers for @releasewise (hint!)
  • Display the number of page views for releasewise.com using the Simple Analytics API.
  • Display remaining days until the end of the month.
  • Measure the ambient light in my office and adjust the brightness of the roof LED panels, using a Milight WIFI bridge controller.

Code

Driving the display

To talk to the Yoctopuce components you need to run their VirtualHub software. Once you have this running you can send HTTP requests to a tiny web server, which transmits low-level commands via USB to the Yoctopuce devices it finds on the USB bus.

For example, this sends Hello to the display:

http://localhost:4444/bySerial/YD128G64-F2BFF/api/display?command=!Hello

(your device ID will be different)

I don’t know why, but the Yoctopuce designers have chosen a weird and poorly documented way to send instructions across HTTP requests. I have plucked the commands I needed from this source code rather than relying on the manual.

The commands for the display I needed are:

  • ^ (or %5E escaped) to clear the display
  • &Small.yfm, &Medium.yfm, and &Large.yfm to set the font size (use %26 to escape the &)
  • m10,10,118,54 to create 10-pixel margin
  • !Foo to print Foo (use %0A to insert line breaks)

Driving the light sensor

The obtain a light sensor reading you call brightness.json which returns a JSON response having currentValue as one of its values (the unit is lux).

Yoctopuce has an odd way of dealing with getting and setting values. For example:

Getting the brightness:

  • http://localhost:4444/bySerial/YD128G64-F2BFF/api/display/brightness.json

Setting the brightness:

  • http://localhost:4444/bySerial/YD128G64-F2BFF/api/display?brightness={value}

You can’t POST a JSON request, everything runs with GETs. Oh well.

Reading page views

Reading the page views for the past 30 days is easy:

SIMPLE_ANALYTICS_ENDPOINT = 'https://simpleanalytics.com/'

def self.pageviews
  response = Typhoeus.get("#{SIMPLE_ANALYTICS_ENDPOINT}releasewise.com.json",
    headers: {
      'api-key': ENV['SIMPLE_ANALYTICS_API_KEY'],
      'content-type': 'content-type: application/json'
    })
  result = JSON.parse(response.body)
  result['pageviews']
end

Obtaining follower count

After spending 10 minutes reading up on Twitter’s API shenanigans I gave up and started looking for a hack.

It turns out, there is a trick to obtain the follower account of any account without resorting to the API. Of course this will be deprecated some day but for now it works:

TWITTER_ENDPOINT = 'https://cdn.syndication.twimg.com/widgets/followbutton/info.json?screen_names=releasewise'

def self.followers_count
  response = Typhoeus.get(TWITTER_ENDPOINT)
  result = JSON.parse(response.body)
  result[0]['followers_count']
end

Sweet!

Counting remaining days

# Days until end of month
last_day = Date.civil(Time.new.year, Time.new.month, -1).day

YoctopuceDisplay.clear
YoctopuceDisplay.small_font
YoctopuceDisplay.print "Days left in #{Date::MONTHNAMES[Time.new.month]}", true
YoctopuceDisplay.large_font
YoctopuceDisplay.print "#{last_day - Time.now.day}"

As you can see I created a couple of helper methods to clean up the code.

Adjust LED panel brightness

I have 4 LED panels in my office which, at full brightness, are too bright for a dark day. I found a nice Ruby gem which offers an API for the Milight WIFI bridge I mentioned before.

I still need to tweak the translation between the measured ambient light (coming from the windows) and the brightness, hue, and saturation of the LED panels. Perhaps I can borrow ideas from f.lux and Apple’s Night Shift.

For now I’ve settled for a simple algorithm that translates the measured brightness to a percentage, which I subtract from 100 in order to adjust the brightness of the 4 LED panels:

require 'milight/v6'
controller = Milight::V6::Controller.new(BRIDGE_IP)
controller.all.brightness(100 - brightness_pct)`

Result

Check out my product Operand, a collaborative tool for due diligences, audits, and assessments.