/**
 * this constructor method is called when the node is created.
 *
 * The options are checked to see if it conforms to our api by using
 * the 'sub_api' field.
 *
 * The private data is guaranteed to be of size 'struct reader_data'.
 *
 * Never send packets from this function as the node is still being
 * created and there are no connections.
 */
static int
reader_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct reader_data *mdata = data;
    const struct sol_flow_node_type_custom_node_types_reader_options *opts;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options,
        SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER_OPTIONS_API_VERSION,
        -EINVAL);
    opts = (const struct sol_flow_node_type_custom_node_types_reader_options *)
        options;

    /* create a 1 second timer where we produce packets. */
    mdata->timer = sol_timeout_add(1000, reader_on_timeout, node);

    /* the initial value comes from options. */
    mdata->val = opts->intopt;

    /* Note that an 'int' port is actually an integer range or a
     * 'struct sol_irange', as it carries not only the value, but how
     * to interpret that integer such as minimum and maximum values
     * (so we can limit to only positive or negative, and smaller
     * precisions) as well how to increment or decrement the value
     * (steps).
     *
     * In this example we are only interested in the value, thus we
     * use the simpler packet constructor.
     */
    return sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT, mdata->val);
}
Beispiel #2
0
static void
check_cb(void *data, int status, const struct sol_update_info *response)
{
    struct sol_flow_node *node = data;
    struct update_data *mdata = sol_flow_node_get_private_data(node);

    if (status < 0) {
        sol_flow_send_error_packet(node, -status,
            "Error while checking for updates: %s", sol_util_strerrora(-status));
        goto end;
    }

#ifndef SOL_NO_API_VERSION
    if (SOL_UNLIKELY(response->api_version != SOL_UPDATE_INFO_API_VERSION)) {
        SOL_WRN("Update info config version '%u' is unexpected, expected '%u'",
            response->api_version, SOL_UPDATE_INFO_API_VERSION);
        return;
    }
#endif

    sol_flow_send_string_packet(node,
        SOL_FLOW_NODE_TYPE_UPDATE_CHECK__OUT__VERSION, response->version);
    sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_UPDATE_CHECK__OUT__SIZE, response->size);
    sol_flow_send_bool_packet(node,
        SOL_FLOW_NODE_TYPE_UPDATE_CHECK__OUT__NEED_UPDATE, response->need_update);

end:
    mdata->handle = NULL;
}
Beispiel #3
0
static void
echo_event_cb(void *data, struct sol_gpio *gpio, bool value)
{
    struct hc_sr04_data *mdata = data;
    struct timespec t2, delta;
    int usec, centimeters;

    /* started the pulse */
    if (value != mdata->low) {
        mdata->t1 = sol_util_timespec_get_current();
        return;
    }

    /* pulse ended */
    t2 = sol_util_timespec_get_current();
    sol_util_timespec_sub(&t2, &mdata->t1, &delta);
    usec = sol_util_usec_from_timespec(&delta);
    /* distance = time * velocity (340 m/s) / 2 */
    centimeters = usec / 58;

    mdata->busy = false;

    sol_flow_send_irange_value_packet(mdata->node,
        SOL_FLOW_NODE_TYPE_HC_SR04_DISTANCE__OUT__CENTIMETERS, centimeters);
}
Beispiel #4
0
static int
_irange_buffer_do(struct irange_buffer_data *mdata)
{
    int32_t result;

    if (!mdata->cur_len)
        return 0;

    result = mdata->normalize_cb(mdata->input_queue, mdata->cur_len);

    return sol_flow_send_irange_value_packet(mdata->node,
        SOL_FLOW_NODE_TYPE_INT_BUFFER__OUT__OUT, result);
}
Beispiel #5
0
static int
abs_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    int32_t value, result;
    int r;

    r = sol_flow_packet_get_irange_value(packet, &value);
    SOL_INT_CHECK(r, < 0, r);

    result = abs(value);

    return sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_INT_ABS__OUT__OUT, result);
}
Beispiel #6
0
static int
delta_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct timestamp_comparison_data *mdata = data;
    struct timespec sub_result;
    time_t result;
    int r;
    int32_t output;

    if (!two_vars_get_value(mdata, port, packet))
        return 0;

    result = mdata->val[1].tv_sec - mdata->val[0].tv_sec;
    if (result > INT32_MAX) {
        sol_flow_send_error_packet(node, ERANGE,
            "Delta is too big for seconds: %s", sol_util_strerrora(ERANGE));
        return 0;
    }
    output = result;

    r = sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_DELTA__OUT__SECONDS, output);
    SOL_INT_CHECK(r, < 0, r);

    sol_util_timespec_sub(&mdata->val[0], &mdata->val[1], &sub_result);
    result = sub_result.tv_sec * NSEC_PER_SEC + sub_result.tv_nsec;

    if (result > INT32_MAX) {
        SOL_DBG("Delta is too big for nanoseconds: %s",
            sol_util_strerrora(ERANGE));
        return 0;
    }
    output = result;

    return sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_DELTA__OUT__NANO_SECONDS, output);
}
Beispiel #7
0
static int
calculate_regexp_substrings(struct string_regexp_search_data *mdata,
    struct sol_flow_node *node)
{
    if (!(mdata->string && mdata->regexp))
        return 0;

    sol_vector_clear(&mdata->substrings);

    mdata->substrings = string_regexp_search_and_split(mdata);

    return sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_STRING_REGEXP_SEARCH__OUT__LENGTH,
        mdata->substrings.len);
}
Beispiel #8
0
static int
min_max_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct irange_comparison_data *mdata = data;
    int32_t *result;
    bool func_ret;

    if (!comparison_func(mdata, node, port, packet, &func_ret))
        return 0;

    if (func_ret)
        result = &mdata->val[0];
    else
        result = &mdata->val[1];

    return sol_flow_send_irange_value_packet(node, 0, *result);
}
static bool
reader_on_timeout(void *data)
{
    /* we get the last parameter we used in sol_timeout_add() */
    struct sol_flow_node *node = data;
    struct reader_data *mdata = sol_flow_node_get_private_data(node);
    int r;

    mdata->val++;

    /* create and send a new int packet on OUT port.
     *
     * Note that an 'int' port is actually an integer range or a
     * 'struct sol_irange', as it carries not only the value, but how
     * to interpret that integer such as minimum and maximum values
     * (so we can limit to only positive or negative, and smaller
     * precisions) as well how to increment or decrement the value
     * (steps).
     *
     * In this example we are only interested in the value, thus we
     * use the simpler packet sender.
     *
     * The port number macro (SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT) is
     * defined in the generated file custom-node-types-gen.h and is
     * based on the JSON array declaration.
     *
     * For efficiency matters soletta will only deal with port
     * indexes, the name is only used by node type description and
     * high-level API to resolve names to indexes.
     */
    r = sol_flow_send_irange_value_packet(node,
        SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT,
        mdata->val);
    if (r < 0) {
        fprintf(stderr, "ERROR: could not send packet on port=%d, value=%d\n",
            SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT, mdata->val);
        /* we will stop running and mdata->timer will be deleted if we
         * return false, then invalidate the handler.
         */
        mdata->timer = NULL;
        return false;  /* stop running */
    }

    return true; /* keep running */
}
Beispiel #10
0
static int
min_max_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct irange_min_max_data *mdata = data;
    int *result;
    int r;

    r = sol_flow_packet_get_irange_value(packet, &mdata->val[port]);
    SOL_INT_CHECK(r, < 0, r);

    mdata->val_initialized[port] = true;
    if (!(mdata->val_initialized[0] && mdata->val_initialized[1]))
        return 0;

    if (mdata->func(mdata->val[0], mdata->val[1]))
        result = &mdata->val[0];
    else
        result = &mdata->val[1];

    return sol_flow_send_irange_value_packet(node, mdata->port, *result);
}
Beispiel #11
0
static void
on_fork_exit(void *data, uint64_t pid, int status)
{
    struct subprocess_data *mdata = data;

    mdata->fork_run = NULL;
    if (mdata->watches.in)
        sol_fd_del(mdata->watches.in);
    if (mdata->watches.err)
        sol_fd_del(mdata->watches.err);
    if (mdata->watches.out) {
        struct write_data *w;
        uint16_t i;
        sol_fd_del(mdata->watches.out);
        SOL_VECTOR_FOREACH_IDX (&mdata->write_data, w, i)
            sol_blob_unref(w->blob);
        sol_vector_clear(&mdata->write_data);
    }

    mdata->watches.in = NULL;
    mdata->watches.err = NULL;
    mdata->watches.out = NULL;
    sol_flow_send_irange_value_packet(mdata->node, SOL_FLOW_NODE_TYPE_PROCESS_SUBPROCESS__OUT__STATUS, status);
}