summaryrefslogtreecommitdiffstats
path: root/controller/ctl-action.c
blob: 5da24e89b6661355eede4b6b857ee5e53b6be227 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 * Copyright (C) 2016 "IoT.bzh"
 * Author Fulup Ar Foll <fulup@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Reference:
 *   Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>

#include "ctl-config.h"


int ActionExecOne(CtlActionT* action, json_object *queryJ) {
    int err;


    switch (action->type) {
        case CTL_TYPE_API:
        {
            json_object *returnJ;

            // if query is empty increment usage count and pass args
            if (!queryJ || json_object_get_type(queryJ) != json_type_object) {
                json_object_get(action->argsJ);
                queryJ = action->argsJ;
            } else if (action->argsJ) {

                // Merge queryJ and argsJ before sending request
                if (json_object_get_type(action->argsJ) == json_type_object) {

                    json_object_object_foreach(action->argsJ, key, val) {
                        json_object_object_add(queryJ, key, val);
                    }
                } else {
                    json_object_object_add(queryJ, "args", action->argsJ);
                }
            }

            json_object_object_add(queryJ, "label", json_object_new_string(action->source.label));

            int err = afb_service_call_sync(action->api, action->call, queryJ, &returnJ);
            if (err) {
                static const char*format = "ActionExecOne(Api) api=%s verb=%s args=%s";
                AFB_ERROR(format, action->api, action->call, action->source.label);
                goto OnErrorExit;
            }
            break;
        }

#ifdef CONTROL_SUPPORT_LUA
        case CTL_TYPE_LUA:
            err = LuaCallFunc(action, queryJ);
            if (err) {
                AFB_ERROR("ActionExecOne(Lua) label=%s func=%s args=%s", action->source.label, action->call, json_object_get_string(action->argsJ));
                goto OnErrorExit;
            }
            break;
#endif

        case CTL_TYPE_CB:
            err = (*action->actionCB) (&action->source, action->argsJ, queryJ);
            if (err) {
                AFB_ERROR("ActionExecOne(Callback) label%s func=%s args=%s", action->source.label, action->call, json_object_get_string(action->argsJ));
                goto OnErrorExit;
            }
            break;

        default:
        {
            AFB_ERROR("ActionExecOne(unknown) API type label=%s", action->source.label);
            goto OnErrorExit;
        }
    }

    return 0;

OnErrorExit:
    return -1;
}


// unpack individual action object

int ActionLoadOne(CtlActionT *action, json_object *actionJ) {
    char *api = NULL, *verb = NULL, *lua = NULL;
    int err, modeCount = 0;
    json_object *callbackJ=NULL;

    err = wrap_json_unpack(actionJ, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}"
            , "label", &action->source.label, "info", &action->source.info, "callback", &callbackJ, "lua", &lua, "api", &api, "verb", &verb, "args", &action->argsJ);
    if (err) {
        AFB_ERROR("ACTION-LOAD-ONE Missing something label|info|callback|lua|(api+verb)|args in:\n--  %s", json_object_get_string(actionJ));
        goto OnErrorExit;
    }

    if (lua) {
        action->type = CTL_TYPE_LUA;
        action->call = lua;
        modeCount++;
    }

    if (api && verb) {
        action->type = CTL_TYPE_API;
        action->api = api;
        action->call = verb;
        modeCount++;
    }

    if (callbackJ) {
        action->type = CTL_TYPE_CB;
        modeCount++;
        err = PluginGetCB (action, callbackJ);
        if (err) goto OnErrorExit;

    }

    // make sure at least one mode is selected
    if (modeCount == 0) {
        AFB_ERROR("ACTION-LOAD-ONE No Action Selected lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
        goto OnErrorExit;
    }

    if (modeCount > 1) {
        AFB_ERROR("ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
        goto OnErrorExit;
    }
    return 0;

OnErrorExit:
    return 1;
};

CtlActionT *ActionLoad(json_object *actionsJ) {
    int err;
    CtlActionT *actions;

    // action array is close with a nullvalue;
    if (json_object_get_type(actionsJ) == json_type_array) {
        int count = json_object_array_length(actionsJ);
        actions = calloc(count + 1, sizeof (CtlActionT));

        for (int idx = 0; idx < count; idx++) {
            json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
            err = ActionLoadOne(&actions[idx], actionJ);
            if (err) goto OnErrorExit;
        }

    } else {
        actions = calloc(2, sizeof (CtlActionT));
        err = ActionLoadOne(&actions[0], actionsJ);
        if (err) goto OnErrorExit;
    }

    return actions;

OnErrorExit:
    return NULL;

}
">) { ERRMSG("cannot data from file \"%s\"",fname); free(filebuf); return 1; } parse_json(jobj); json_object_put(jobj); free(filebuf); return 0; } static int parse_gear_para_json(json_object *obj) { int err = 0; json_object * obj_speed_para; char *pos_name = NULL; double pos_val = 0; json_object_object_foreach(obj, key, val) { if (strcmp(key,"GEAR_PARA") == 0) { enum json_type type = json_object_get_type(val); if (type == json_type_array) { int array_len = json_object_array_length(val); NOTICEMSG("array_len:%d!", array_len); for (int i = 0; i < array_len; i++) { obj_speed_para = json_object_array_get_idx(val, i); if(obj_speed_para) { json_object_object_foreach(obj_speed_para, key, val) { /// if (strcmp("POS", key) == 0) { pos_name = (char *)json_object_get_string(val); } else if(strcmp("VAL", key) == 0) { pos_val = json_object_get_double(val); } /// if(strcmp("First", pos_name) == 0) { gearRatio[1] = (double)(1.0 / pos_val); } else if(strcmp("Second", pos_name) == 0) { gearRatio[2] = (double)(1.0 / pos_val); } else if(strcmp("Third", pos_name) == 0) { gearRatio[3] = (double)(1.0 / pos_val); } else if(strcmp("Fourth", pos_name) == 0) { gearRatio[4] = (double)(1.0 / pos_val); } else if(strcmp("Fifth", pos_name) == 0) { gearRatio[5] = (double)(1.0 / pos_val); } else if(strcmp("Sixth", pos_name) == 0) { gearRatio[6] = (double)(1.0 / pos_val); } else if(strcmp("Reverse", pos_name) == 0) { gearRatio[7] = (double)(1.0 / pos_val); } } } } } else { ERRMSG("json: Need array \"%s\"", key); } } else { ERRMSG("json: Unknown key \"%s\"", key); } } return err; } int wheel_gear_para_init(const char *fname) { struct json_object *jobj; int fd_gear_para; struct stat stbuf; char *filebuf; fd_gear_para = afb_daemon_rootdir_open_locale(fname, O_RDONLY, NULL); if (fd_gear_para < 0) { ERRMSG("gear para is not access"); return -1; } FILE *fp = fdopen(fd_gear_para,"r"); if (fp == NULL) { ERRMSG("canno read gear para file"); return -1; } if (fstat(fd_gear_para, &stbuf) == -1) { ERRMSG("cant get file state.\n"); return -1; } filebuf = (char*)malloc((size_t)stbuf.st_size); fread(filebuf, 1, (size_t)stbuf.st_size, fp); fclose(fp); jobj = json_tokener_parse(filebuf); if (jobj == NULL) { ERRMSG("cannot data from file \"%s\"",fname); free(filebuf); return 1; } parse_gear_para_json(jobj); json_object_put(jobj); free(filebuf); return 0; } struct json_object *property2json(struct prop_info_t *property) { struct json_object *jobj; struct json_object *nameObject = NULL; struct json_object *valueObject = NULL; if (property == NULL) return NULL; jobj = json_object_new_object(); if (jobj == NULL) return NULL; switch(property->var_type) { case VOID_T: /* FALLTHROUGH */ case INT8_T: /* FALLTHROUGH */ case INT16_T: /* FALLTHROUGH */ case INT_T: /* FALLTHROUGH */ case INT32_T: /* FALLTHROUGH */ case INT64_T: /* FALLTHROUGH */ case UINT8_T: /* FALLTHROUGH */ case UINT16_T: /* FALLTHROUGH */ case UINT_T: /* FALLTHROUGH */ case UINT32_T: /* FALLTHROUGH */ case ENABLE1_T: valueObject = json_object_new_int(propertyValue_int(property)); break; case BOOL_T: valueObject = json_object_new_boolean(property->curValue.bool_val); break; default: ERRMSG("Unknown value type:%d", property->var_type); break; } if (valueObject == NULL) { ERRMSG("fail json ValueObject"); json_object_put(jobj); return NULL; } nameObject = json_object_new_string(property->name); json_object_object_add(jobj, "name", nameObject); json_object_object_add(jobj, "value", valueObject); return jobj; }