research application on sending data to headend

Dependencies:   DataStore JobScheduler NetworkServices W5500Interface nanopb protocol

See "main.cpp" documentation on "API Documentation" tab for details about application.

source/main.cpp

Committer:
sgnezdov
Date:
2017-08-04
Revision:
22:3af582d8e227
Parent:
21:32cd3bfde206

File content as of revision 22:3af582d8e227:

#include "mbed.h"

#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP  "main"

#include "scheduler.h"
#include "schedules.h"
#include "jobService.h"
#include "netstack.h"
#include "config.h"
#include "lceProxy.h"

#include "jobTestPrint.h"
#include "jobFakeADC.h"
#include "jobSchedulesUpload.h"
#include "jobTestUpload.h"

/** TracingLock provides a single synhronization point for tracing library. */
static Mutex TracingLock;

/** @brief Implements trace library locking policy, which is to synchronize its output. */
static void tracingWait()
{
    TracingLock.lock();
}

/** @brief Implements tracing library release policy. */
static void tracingRelease()
{
    TracingLock.unlock();
}

static bool initTime()
{
    struct tm clock;
    clock.tm_year = 2001 - 1900;
    clock.tm_mon = 0;
    clock.tm_mday = 1;
    clock.tm_hour = 13;
    clock.tm_min = 30;
    clock.tm_sec = 0;
    // time_t is in seconds
    time_t time = mktime(&clock);
    if (time == (time_t) - 1) {
        error("Error setting clock.");
        return false;
    }
    set_time(time);
    printf("Time is set to: %s\n", ctime(&time));
    return true;
}

/** 
\brief Application entry point.

Main up execution environment.

Sets up tracing environment to be thread safe.

Initializes services such as networking stack, LCE proxy and others.

Configures and starts scheduler service that's at the core of the application
functinality and design.

Associates job type IDs with functions that implement high level job concept.

If you need to add new functionality create it a a standalone C function
or C++ adapter function backed by C++ object state and register it with
scheduler service registry.

Some jobs can be created in the main to bootstrap application functionality.

Piggybacked commands can change internal scheduler state by adding new jobs
or removing existing jobs.

@see main.h for design details.
*/
int main()
{
    Serial pc(USBTX, USBRX);
    pc.baud(115200);

    printf("\n==Borsch==\n");
    
//    if (initTime() == false) {
//        printf("Application terminated: initTime has failed\n");
//        exit(1);
//    }
    
    /* Setup tracing */
    mbed_trace_mutex_wait_function_set( tracingWait ); // only if thread safety is needed
    mbed_trace_mutex_release_function_set( tracingRelease ); // only if thread safety is needed
    mbed_trace_init();       // initialize the trace library
    
    tr_info("**Started**");    //-> "[INFO][main]: this is an info msg"
    osThreadId_t tid = osThreadGetId();
    tr_debug("Main thread ID: 0x%X", tid);
    
    Config conf("Nucleo1");

    uint8_t mac_addr[6] = {0x00, 0x08, 0xdc, 0x45, 0x56, 0x67};
    NetworkInterface* nif = initNetworkStack(mac_addr);
    if (nif == NULL) {
        tr_error("**Terminated**");
        exit(0);
    }
    
    LceProxy lce(*nif, conf);
    
    JobScheduler::JobService js;   
    JobScheduler::Scheduler scheduler(&js);
   
    /* Job Type ID shall match command id defined in ISOM commandTypes.go
    While this rule is not strictly necessary it cuts down on code responsible
    for mapping between our internal IDs to CommandIDs.
    
    addKV(NewCommandMetaData(1, "NO-OP"))
    addKV(NewCommandMetaData(2, "List Schedules"))
    addKV(NewCommandMetaData(3, "Add Schedule"))
    addKV(NewCommandMetaData(4, "Remove Schedule"))
    addKV(NewCommandMetaData(5, "Set STM ADC Schedule"))
    addKV(NewCommandMetaData(31, "Close Valve"))
    addKV(NewCommandMetaData(32, "Open Valve"))
    
    Use range 1000 for unique to STM jobs.
    */

    // command #2 is List Schedules in ISOM.
    JobSchedulesUpload jSchedulesUpload(conf, lce, scheduler);
    js.Register(2, JobSchedulesUpload::RunAdapter, &jSchedulesUpload);
    
    JobTestPrint jTestPrint;
    js.Register(1001, JobTestPrint::RunAdapter, &jTestPrint);
    
    JobFakeADC jFakeADC(lce);
    js.Register(1002, JobFakeADC::RunAdapter, &jFakeADC);
    
    JobTestUpload jTestUpload(lce);
    js.Register(1003, JobTestUpload::RunAdapter, &jTestUpload);

    scheduler.Start();
    
    // inject test case
    time_t nowSecs = time(NULL);
    // NOTE: don't schedule run once with at 0, because 0 means never.
    //JobScheduler::Response<JobScheduler::JobID> res =
    scheduler.JobAdd(1001, new JobScheduler::RunOnceSchedule(nowSecs+31), NULL);
    scheduler.JobAdd(1001, new JobScheduler::RunOnceSchedule(nowSecs+32), NULL);
    scheduler.JobAdd(1001, new JobScheduler::RunOnceSchedule(nowSecs+33), NULL);
    scheduler.JobAdd(2, new JobScheduler::RunOnceSchedule(nowSecs), NULL);
//    
//    scheduler.JobAdd(2, new JobScheduler::RunPeriodicSchedule(10, 3), NULL);
//    scheduler.JobAdd(1001, new JobScheduler::RunPeriodicSchedule(5, 10), NULL);
    
        //scheduler.JobAdd(1002, new JobScheduler::RunOnceSchedule(1), NULL);
        //scheduler.JobAdd(1001, new JobScheduler::RunOnceSchedule(nowSecs + 2), NULL);
    //res = scheduler.JobAdd(1002, new JobScheduler::RunPeriodicSchedule(2, 5), NULL);
    
    // block forever unless there is a job that calls scheduler.Stop()
    scheduler.WaitToStop();   
    
    /* we can somehow load new application image here and restart */
    
    // indicate clean app termination
    tr_info("**Finished**");    //-> "[INFO][main]: this is an info msg"    
    exit(0);
}