Eric Ely
Published © LGPL

IoT Code Deployer-er

A code deployer-er remote for building and deploying projects, for the IoT fanatic who can't be bothered to sign into a build server.

BeginnerFull instructions provided1 hour695
IoT Code Deployer-er

Things used in this project

Story

Read more

Code

Build DeployBot Webhook

JSON
The json webhook to trigger a build
{
    "url": "https://bluz.deploybot.com/api/v1/deployments",
    "deviceID": "BLUZ_DEVICE_TO_TRIGGER_WEBHOOK",
    "event": "BuildDeployBotConsole",
    "mydevices": true,
    "requestType": "POST",
    "headers": {
      "X-Api-Token": "DEPLOY_BOT_TOKEN"
    },
    "json": {
      "environment_id": "ID_OF_THE_DEPLOY_BOT_ENVIRONMENT",
      "trigger_notifications": true,
      "comment": "Deploy via API"
    },
    "noDefaults": false,
    "rejectUnauthorized": true,
    "responseTemplate": "{{id}}",
    "responseTopic": null
  }

Get DeployBot Webhook

JSON
The json webhook to get a builds status
{
    "url": "https://yoursubdomain.deploybot.com/api/v1/deployments/{{PARTICLE_EVENT_VALUE}}",
    "deviceID": "BLUZ_DEVICE_TO_TRIGGER_WEBHOOK",
    "event": "GetDeployBotConsole",
    "mydevices": true,
    "requestType": "GET",
    "headers": {
      "X-Api-Token": "DEPLOY_BOT_TOKEN"
    },
    "noDefaults": false,
    "rejectUnauthorized": true,
    "responseTemplate": "{{state}}",
    "responseTopic": null
  }

bluz firmware

C/C++
Code to run on bluz to control Modulo and publish events to/from DeployBot
// This #include statement was automatically added by the Particle IDE.
#include "application.h"
#include "Modulo.h"

// Declare callback functions for knob and display
void onKnobPressed(KnobModulo &k);
void onKnobTurned(KnobModulo &k);
void onButtonPress(DisplayModulo &d, int button);

// Create an object that represents the knob
KnobModulo knob;

// Create an object that represents the display
DisplayModulo display;

const char *builds[] = {"Console", "Website", "Docs" };
int buildsLength = 3;
int sections = 360/buildsLength;
int currentIndex;

int turnOffInterval = 12000;
int timeToTurnOff = turnOffInterval;

enum UserState {
    Toggling,
    Confirmation,
    WaitingForID,
    WaitingForBuild,
    BuildDone
};
UserState state = Toggling;
String buildState;

void setState(UserState newState) {
    state = newState;
    switch (state) {
        case Toggling:
            display.clear();
            display.refresh();
            knob.setHSV(0, 0, 0);
            break;
        case Confirmation:
            char confirmString[36];
            sprintf(confirmString,"deploy %s?",builds[currentIndex]);
            display.clear();
            display.println("Are you sure you");
            display.println("want to build and");
            display.println(confirmString);
            display.println("");
            display.println("");
            display.println("");
            display.println("Yes           No");
            display.refresh();
            break;
        case WaitingForID:
            display.clear();
            display.setTextColor(0,255,0);
            display.println("Building!");
            char pubString[60];
            sprintf(pubString,"BuildDeployBot%s",builds[currentIndex]);
            Particle.publish(pubString, PRIVATE);
//            Particle.publish("hook-response/BuildDeployBotConsole/0", String(5175198));
            break;
        case WaitingForBuild:
            break;
        case BuildDone:
            display.clear();
            display.refresh();
            if (buildState == "failed") {
                knob.setColor(255,0,0);
                display.setTextColor(255,0,0);
                display.println("  FAILED!");
            } else if (buildState == "success") {
                knob.setColor(0,255,0);
                display.setTextColor(0,255,0);
                display.println("  SUCCESS!");
            } else if (buildState == "skipped") {
                knob.setColor(255,255,0);
                display.setTextColor(255,255,0);
                display.println("  SKIPPED!");
            }
            display.refresh();
            delay(8000);
            setState(Toggling);
            break;
    }

}

String buildID;
void buildCallHandler(const char *event, const char *data) {
    // Handle the webhook response
    buildID = String(data);
    setState(WaitingForBuild);
}

void buildGetHandler(const char *event, const char *data) {
    // Handle the webhook response
    buildState = String(data);
}

// The setup function is run once, when the program starts
void setup() {
    pinMode(D7, OUTPUT);
    //Callbacks for build webhooks
    Particle.subscribe("hook-response/BuildDeployBot", buildCallHandler, MY_DEVICES);

    //Callbacks for get status webhooks
    Particle.subscribe("hook-response/GetDeployBot", buildGetHandler, MY_DEVICES);

    // Attach the callback function to the knob and display
    knob.setButtonPressCallback(onKnobPressed);
    knob.setPositionChangeCallback(onKnobTurned);

    display.setButtonPressCallback(onButtonPress);

    // Run the callback once to set the initial text
    onKnobTurned(knob);
}

int hue = 0;
int hueIncr = 0.05;
int publishIncr = 5;
// The loop function is run constantly
void loop() {
    // Always call Modulo.loop() at the top of the loop function. It's
    // communicates with the modulos and executes callbacks if any events
    // have occured.
    Modulo.loop();

    if (millis() > timeToTurnOff && state < WaitingForID) {
        setState(Toggling);
    }

    if (state == WaitingForBuild) {
        knob.setHSV(hue, 0, 1.0);
        hue+=hueIncr;
        if (hue >= 360) {hue = 0;}
        delay(200);
        if (buildState == "failed" || buildState == "success" || buildState == "skipped") {
            setState(BuildDone);
        }
        if (publishIncr++ > 4) {
            publishIncr = 0;
            char pubString[60];
            sprintf(pubString,"GetDeployBot%s",builds[currentIndex]);
            Particle.publish(pubString, buildID, PRIVATE);
        }
    }

    System.sleep(SLEEP_MODE_CPU);
}

bool testRange(int numberToCheck, int bottom, int top)
{
    return (numberToCheck >= bottom && numberToCheck <= top);
}

int findIndex(int num) {
    for (int i = 0; i < buildsLength; i++) {
        if (testRange(num, i*sections, (i+1)*sections)) {
            return i;
        }
    }
    return 0;
}

void onKnobPressed(KnobModulo &k) {

    if (millis() > timeToTurnOff) {
        //if the screen was off, just turn it back on for 6 seconds
        timeToTurnOff = millis() + turnOffInterval;
    } else {
        //if the screen was on, move to the next stage
        switch (state) {
            case Toggling:
                setState(Confirmation);
                break;
            case Confirmation:
                break;
        }
    }
}

// This is our callback function. It will run when the knob is presed or turned.
void onKnobTurned(KnobModulo &k) {
    if (state != Toggling) {
        return;
    }

    // Get the angle of the knob. The angle is between 0 and 360
    float angle = k.getAngle();
    display.clear();
    int index = findIndex(angle);
    display.println(builds[index]);
    currentIndex = index;
    display.refresh();

    // Convert the angle (between 0 and 360) to a hue (between 0 and 1)
    float hue = angle/360.0;

    // The saturation is 0 if the button is pressed and 1 otherwise.
    float saturation = 1-k.getButton();

    // Set the knob's color
    k.setHSV(hue, saturation, 1.0);

    timeToTurnOff = millis() + turnOffInterval;
}

void onButtonPress(DisplayModulo &d, int button) {
    if (state != Confirmation) {
        return;
    }

    // Draw different text, in a different color, based on which button is pressed.
    switch (button) {
        case 0:
            setState(WaitingForID);
            break;
        case 2:
            //They pressed no
            setState(Toggling);
            break;
    }

    // Nothing will actually show up on the display until you call refresh.
    display.refresh();
}

Credits

Eric Ely

Eric Ely

9 projects • 36 followers
maker, breaker, fixer, and tinkerer. interested in building products that get technology out of the way and actually make your life easier.

Comments