void loop() {
    for(int i = 0; i < getCanBusCount(); i++) {
        receiveCan(&getCanBuses()[i]);
    }

    readFromHost(listener.usb, receiveWriteRequest);
    readFromSerial(listener.serial, receiveWriteRequest);
    readFromSocket(listener.ethernet, receiveWriteRequest);

    for(int i = 0; i < getCanBusCount(); i++) {
        processCanWriteQueue(&getCanBuses()[i]);
    }

    updateDataLights();
}
/* Public: Update the color and status of a board's light that shows the status
 * of the CAN bus. This function is intended to be called each time through the
 * main program loop.
 */
void updateDataLights() {
    static bool busWasActive;
    bool busActive = false;
    for(int i = 0; i < getCanBusCount(); i++) {
        busActive = busActive || canBusActive(&getCanBuses()[i]);
    }

    if(!busWasActive && busActive) {
        debug("CAN woke up - enabling LED");
        enable(LIGHT_A, COLORS.blue);
        busWasActive = true;
    } else if(!busActive && busWasActive) {
#ifndef TRANSMITTER
        debug("CAN went silent - disabling LED");
        busWasActive = false;

        // TODO I don't love having all of this here, but it's the best place
        // for now. Maybe the modules need a deinitializeFoo() method in
        // addition to the initialize one.
        disable(LIGHT_A);
        disable(LIGHT_B);
        setBluetoothStatus(false);

        // Make sure lights and Bluetooth are disabled before sleeping
        delayMs(100);
        enterLowPowerMode();
#endif
    }
}
void receiveRawWriteRequest(cJSON* idObject, cJSON* root) {
    uint32_t id = idObject->valueint;
    cJSON* dataObject = cJSON_GetObjectItem(root, "data");
    if(dataObject == NULL) {
        debug("Raw write request missing data", id);
        return;
    }

    char* dataString = dataObject->valuestring;
    char* end;
    // TODO hard coding bus 0 right now, but it should support sending on either
    CanMessage message = {&getCanBuses()[0], id};
    enqueueCanMessage(&message, strtoull(dataString, &end, 16));
}
void initializeAllCan() {
    for(int i = 0; i < getCanBusCount(); i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}