Saturday, 29 June 2019

Search WhatsApp Messages on iPhone

I recently had urgent need to search for a snippet of information in my WhatsApp message history.

How to do this was not obvious and I ended up off on a tangent, searching google for how to search WhatsApp. Unfortunately the results were long-winded articles beginning with an introduction to WhatsApp, why one would want to use it and so on, riddled with adverts and clickbait. When I finally scrolled down to the part containing the information I needed, it was incorrect - perhaps written for an old version of the app.

How to search through WhatsApp messages on iOS - concise version

  1. Go to the chat or group containing the messages that you want to search
  2. Tap the contact or group name at the top
  3. The "Group Info" or "Contact Info" screen opens. Third down is Chat Search, tap this link
  4. Enter the search text.
  5. The search is case-insensitive. You can move up/down through the matches using ^ v buttons to the left of the match counter

I hope this helps someone needing a quick answer to a simple problem.

Monday, 6 May 2019

BA Heritage Liveries

On August 25, 1919, British Airways’ forerunner company, Aircraft Transport and Travel Limited (AT&T), launched the world's first daily international scheduled air service between London and Paris.


To mark the centenary year, four aircraft have been repainted in heritage livery:


Ref. BA press release



Monday, 24 September 2018

Containerisation cheat-sheet

A list of useful Docker, Kubernetes and Helm commands

Basic Docker container management

  • $ docker images - list locally cached images
  • $ docker container ls - list running containers
  • $ docker container stop containername - stop a running container
  • $ docker container rm containername - remove a running container

Local Docker Registry

  • $ docker run --detach --publish 5000:5000 --restart=always --name=registry registry:2 - run a local registry in the background
    The first port number refers to the local host, the second is the port within the container.
  • $ docker tag imagename localhost:5000/myimagename - To push to a particular registry, first tag the image with the first part as hostname:port.
  • $ docker push localhost:5000/myimagename - push myimagename from the local docker cache to the local registry
  • $ docker pull localhost:5000/myimagename - pull myimagename from the local registry to the local docker cache

Kubernetes

The official cheat-sheet is pretty detailed, the shortlist below are my "beginners basics":
  • $ kubectl version
  • $ kubectl get nodes
  • $ kubectl config get-contexts
  • $ kubectl config current-context
  • $ kubectl config use-context
  • $ kubectl config view
  • $ kubectl get deployments
  • $ kubectl delete deployment name
  • $ kubectl get pods [-o wide|yaml|json|go-template=] - list deployed pod names
  • $ kubectl get pod --watch pod-name - follow pod status changes
  • $ kubectl describe pod/pod-name - print detailed pod status and event transitions - useful for start-up diagnostics
  • $ kubectl delete pod/pod-name
  • $ kubectl get services
  • $ kubectl describe service name
  • $ kubectl delete service -l run=name
  • $ kubectl logs pod-name - print pod application logs
  • $ kubectl exec -ti pod-name -- bash
  • $ kubectl exec -ti pod-name -- curl localhost:8080

Helm

Helm is an 'orchestration' service. It co-ordinates all of those separate Kubernetes configurations that are required to set up your application. Essentially it allows you to write Kubernetes config files as templates, extracting the variables to a top-level 'values.yaml' file, supporting a level of re-use and abstracting away some of Kubernetes' complexity. You must still learn the Kubernetes API though, and now also some {{ Go }} syntax too...
  • $ helm list - list deployments
  • $ helm install [--debug] [--dry-run] chartdir - deploy the given chart to the cluster
  • $ helm delete ... - opposite of install
  • $ helm status ... - print deployment status

YAML

Of course, you also need to learn YAML syntax. This cheat-sheet is the most helpful I've found so far. Scroll down to the Examples section.
The YAML spec website is a daunting place to start for something essentially so simple, but it does include a short refcard which may become useful once you know what it all means.

Saturday, 20 January 2018

Model Aircraft Navigation Light Controller

Brian asked whether I could build him a circuit to flash the navigation lights on a model aircraft in a realistic manner.  He had previously provided me with an Arduino Nano which would easily be capable of the task, actually it seems like overkill, but software does make this kind of thing very easy.

Searching the Internet yielded a diagram explaining the actual light flash timings for an Airbus, which seems like a fair starting point.

(Source: UTC Aerospace Systems)

Programming the Arduino to emulate the timings behind this behaviour required a simple state machine.
The way I've coded it here isn't going to be very power-efficient though, since it's spinning around the loop all the time. It would be better to add some sleep logic and make it interrupt driven. Maybe later.

const int pinWingL =  2;
const int pinWingR =  3;
const int pinTail =  4;
const int pinBeacon =  LED_BUILTIN;

// Start time of state machine
unsigned long startTime = 0;

// Current state
int state = 0;

void setup() {
  // set the digital pins as output:
  pinMode(pinWingL, OUTPUT);
  pinMode(pinWingR, OUTPUT);
  pinMode(pinTail, OUTPUT);
  pinMode(pinBeacon, OUTPUT);
}


void loop() {

  unsigned long currentTime = millis();
  long deltaTime = currentTime - startTime;
  
  switch (state) {
    case (0): 
    default:
      startTime = currentTime;
      setBeacon(LOW);
      setWing(HIGH);
      setTail(HIGH);
      state = 1;
      break;

    case (1):
      if (deltaTime > 50) {
        setWing(LOW);
        state = 2;
      }
      break;

    case (2): 
      if (deltaTime > 100) {
        setWing(HIGH);
        setTail(LOW);
        state = 3;
      }
      break;

    case (3):
      if (deltaTime > 150) {
        setWing(LOW);
        state = 4;
      }
      break;

    case (4):
      if (deltaTime > 500) {
        setBeacon(HIGH);
        state = 5;
      }
      break;

    case (5):
      if (deltaTime > 600) {
        setBeacon(LOW);
        state = 6;
      }
      break;

    case (6):
      if (deltaTime > 999) {
        startTime = currentTime;
        state = 0;
      }
      break;
  }         
}

void setWing(int state) {
  digitalWrite(pinWingL, state);
  digitalWrite(pinWingR, state);
}

void setTail(int state) {
  digitalWrite(pinTail, state);
}

void setBeacon(int state) {
  digitalWrite(pinBeacon, state);
}

Saturday, 15 July 2017

Running Light Controller

My friend Brian Boot is a modeller.  He's not just any old modeller who assembles a few Airfix kits in his spare time though, he's absolutely dedicated to model making at the highest level, adding additional details and working features wherever possible.  If you visit his house, you have to be careful moving around, because almost all horizontal space has been taken over by models and work-in-progress building more models.  His work has won medals at competitions and some are displayed in museums, I believe you can see some at the Shoreham aircraft museum. He also has galleries on the Farnborough and West Middlesex club websites.

One thing that sets Brian apart from many other model makers is his desire to add lights and motors where possible.  One of his works-in-progress is a Bandai 1/16 scale Showman's Engine (link shows another finished example) but it had reached a state of impasse due to his desire to illuminate the canopy with some chasing lights and motorise the mechanism.  I set about designing a circuit for the lights, so he could get on and finish it.

There are a lot of circuits for this type of thing using a microcontroller, but really that isn't necessary, the basic circuit is almost a classic from the 1980s, a 555 timer driving a 4017 decade counter.  The hard part (as far as I was concerned) was to find a good way of driving the LEDs properly using constant-current source.

If the LEDs were simply wired in parallel, each with its own resistor, the overall current required would be multiplied by the number of LEDs, the wiring would become more of a mess with the resistors needing to be embedded up in the roof of the model, it wasn't going to be ideal.  I needed to connect the LEDs in series so that the current for each set of lights could be set correctly,  this would equalise the brightness, avoid over-driving them, and keep the circuit simpler with reduced wiring.

The constant-current driver design was taken from an excellent Instructable "High Power LED Driver Circuits" using the final circuit at step 8 with the zener diode.  Each LED requires a forward voltage of between 2 and 3 volts (depending on colour) so a DC-DC boost converter (from ebay) provides the 30v necessary for 10 LEDs in series.

Circuit diagram:
 Stripboard layout:
Prototype: