Beispiel #1
0
static int
constant_boolean_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    const struct sol_flow_node_type_constant_boolean_options *opts;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options,
        SOL_FLOW_NODE_TYPE_CONSTANT_BOOLEAN_OPTIONS_API_VERSION, -EINVAL);
    opts = (const struct sol_flow_node_type_constant_boolean_options *)options;

    return sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_CONSTANT_BOOLEAN__OUT__OUT, opts->value);
}
Beispiel #2
0
/* GPIO READER ********************************************************************/
static void
gpio_reader_event(void *data, struct sol_gpio *gpio)
{
    int value;
    struct sol_flow_node *node = data;
    struct gpio_data *mdata = sol_flow_node_get_private_data(node);

    value = sol_gpio_read(mdata->gpio);
    SOL_INT_CHECK(value, < 0);

    sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_GPIO_READER__OUT__OUT, value);
}
Beispiel #3
0
static int
udev_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct udev_data *mdata = data;
    struct udev_device *device;
    bool value;
    const struct sol_flow_node_type_udev_boolean_options *opts =
        (const struct sol_flow_node_type_udev_boolean_options *)options;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options,
        SOL_FLOW_NODE_TYPE_UDEV_BOOLEAN_OPTIONS_API_VERSION, -EINVAL);

    mdata->udev = udev_new();
    SOL_NULL_CHECK(mdata->udev, -EINVAL);

    mdata->monitor = udev_monitor_new_from_netlink(mdata->udev, "udev");
    if (!mdata->monitor) {
        SOL_WRN("Fail on create the udev monitor");
        goto monitor_error;
    }

    if (udev_monitor_enable_receiving(mdata->monitor) < 0) {
        SOL_WRN("error: unable to subscribe to udev events");
        goto receive_error;
    }

    mdata->addr = strdup(opts->address);

    mdata->node = node;
    mdata->watch = sol_fd_add(udev_monitor_get_fd(mdata->monitor),
        SOL_FD_FLAGS_IN | SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP,
        _on_event, mdata);

    device = udev_device_new_from_syspath(mdata->udev, mdata->addr);
    if (device) {
        value = true;
        udev_device_unref(device);
    } else {
        value = false;
    }

    return sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_UDEV_BOOLEAN__OUT__OUT, value);

receive_error:
    mdata->monitor = udev_monitor_unref(mdata->monitor);
monitor_error:
    mdata->udev = udev_unref(mdata->udev);
    return -EINVAL;
}
Beispiel #4
0
static int
inrange_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
    const struct sol_flow_packet *packet)
{
    int r;
    int32_t value;
    struct sol_irange *mdata = data;

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

    return sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_INT_INRANGE__OUT__OUT,
        value >= mdata->min && value <= mdata->max);
}
Beispiel #5
0
/*
 * WARNING: Do NOT use it for anything else than test purposes.
 */
static int
random_boolean_generate(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct random_node_data *mdata = data;
    bool value;
    int r;

    r = sol_random_get_bool(mdata->engine, &value);
    if (r < 0)
        return r;

    return sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_RANDOM_BOOLEAN__OUT__OUT,
        value);
}
static int
logic_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    int r;
    struct sol_irange in_value;

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    r = sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_LOGIC__IN__IN,
        in_value.val % 2 == 0);

    return 0;
}
Beispiel #7
0
static void
on_minutes_packet(void *data, struct sol_flow_node *n, uint16_t port, const struct sol_flow_packet *packet)
{
    int32_t value = get_int32_packet_and_log(n, port, packet);
    static int i = 0;

    if (value < 0)
        return;

    /* do some logic.
     *
     * Here we will disconnect the 'OUT' output port from 'seconds',
     * this would have single-node to stop delivering packets on that
     * port to 'on_seconds_packet()', if running with
     * SOL_LOG_LEVELS=sol-flow:4 you'd see that packets were dropped.
     *
     * And we send a boolean packet with value 'false' to the input
     * port 'ENABLED' of 'seconds' node so it will stop emitting these
     * packets.
     *
     * in the next minute we reverse it, re-connecting the 'OUT' port
     * and sending true to 'ENABLED'.
     */
    i++;
    if (i == 1)
        return; /* first time let it go */
    if (i % 2 == 0) {
        puts("stop seconds and disconnect output port, will change in 1 minute");
        sol_flow_single_port_out_disconnect(seconds, seconds_port_out);
        sol_flow_send_boolean_packet(seconds, seconds_port_enabled, false);
    } else {
        puts("start seconds and connect output port, will change in 1 minute");
        sol_flow_single_port_out_connect(seconds, seconds_port_out);
        sol_flow_send_boolean_packet(seconds, seconds_port_enabled, true);
    }
}
Beispiel #8
0
static int
filter_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    bool packet_val;
    uint16_t out_port;
    int r;

    r = sol_flow_packet_get_boolean(packet, &packet_val);
    SOL_INT_CHECK(r, < 0, r);
    if (packet_val)
        out_port = SOL_FLOW_NODE_TYPE_BOOLEAN_FILTER__OUT__TRUE;
    else
        out_port = SOL_FLOW_NODE_TYPE_BOOLEAN_FILTER__OUT__FALSE;
    return sol_flow_send_boolean_packet(node, out_port, packet_val);
}
Beispiel #9
0
static void
install_cb(void *data, int status)
{
    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 installing update: %s", sol_util_strerrora(-status));
    }

    sol_flow_send_boolean_packet(node,
        SOL_FLOW_NODE_TYPE_UPDATE_INSTALL__OUT__SUCCESS, status == 0);

    mdata->handle = NULL;
}
Beispiel #10
0
static int
comparison_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;
    const struct timestamp_comparison_node_type *type;
    bool output;

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

    type = (const struct timestamp_comparison_node_type *)
        sol_flow_node_get_type(node);

    output = type->func(&mdata->val[0], &mdata->val[1]);

    return sol_flow_send_boolean_packet(node, 0, output);
}
Beispiel #11
0
/*
 * isodd is a very simplistic type, it only handle a single event and
 * has no storage/context. All it does is get an integer and send a
 * boolean true if that number is odd, sending false if it's even.
 */
static int
isodd(struct sol_flow_node *node, const struct sol_flow_simplectype_event *ev, void *data)
{
    int32_t val;
    int r;

    /* we only handle events for port input. */
    if (ev->type != SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_PORT_IN_PROCESS)
        return 0;

    /* get the integer value from irange and check if it worked */
    r = sol_flow_packet_get_irange_value(ev->packet, &val);
    if (r < 0)
        return r;

    /* we use port index '0' here, after all we have a single port */
    return sol_flow_send_boolean_packet(node, 0, (val % 2 != 0));
}
Beispiel #12
0
static void
_write_byte(struct sol_flow_node *node, unsigned char byte)
{
    int i;
    struct segments_ctl_data *mdata = sol_flow_node_get_private_data(node);

    if (mdata->needs_clear) {
        _clear(node);
        mdata->needs_clear = false;
    }

    // Unless we set active_low on the data gpio, it expects 1 for the led
    // to be off, and 0 for on, so we invert the byte here.
    byte = ~byte;
    for (i = 0; i < 8; i++) {
        int val = (byte >> i) & 1;
        sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_CALAMARI_SEGMENTS_CTL__OUT__DATA, val);
        _tick(node);
    }
    _latch(node);
}
Beispiel #13
0
static bool
_on_event(void *data, int fd, uint32_t cond)
{
    struct udev_data *mdata = data;
    struct udev_device *device;
    bool event, inform = true;
    const char *action;

    if (cond & (SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP)) {
        SOL_WRN("Error with the monitor");
        mdata->watch = NULL;
        sol_flow_send_error_packet(mdata->node, EIO, NULL);
        return false;
    }

    device = udev_monitor_receive_device(mdata->monitor);
    if (device == NULL)
        return true;

    if (mdata->addr && !streq(udev_device_get_syspath(device), mdata->addr))
        goto end;

    action = udev_device_get_action(device);
    if (streq(action, "add"))
        event = true;
    else if (streq(action, "remove"))
        event = false;
    else
        inform = false;

    if (inform)
        sol_flow_send_boolean_packet(mdata->node,
            SOL_FLOW_NODE_TYPE_UDEV_BOOLEAN__OUT__OUT,
            event);

end:
    udev_device_unref(device);
    return true;
}
Beispiel #14
0
static bool
timer_tick(void *data)
{
    struct sol_flow_node *node = data;
    struct boolean_generator_data *mdata = sol_flow_node_get_private_data(node);
    bool out_packet;

    if (*mdata->it == 'T') {
        out_packet = true;
    } else if (*mdata->it == 'F') {
        out_packet = false;
    } else {
        sol_flow_send_error_packet(node, ECANCELED,
            "Unknown sample: %c. Option 'sequence' must be composed by 'T' and/or 'F' chars.");
        return false;
    }

    sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_TEST_BOOLEAN_GENERATOR__OUT__OUT,
        out_packet);

    mdata->it++;
    return *mdata->it != '\0';
}
Beispiel #15
0
static int
localtime_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct timespec value;
    struct tm split_time;
    struct sol_irange year = { 0, 0, INT32_MAX, 1 };
    struct sol_irange mon = { 0, 0, 11, 1 };
    struct sol_irange mday = { 0, 1, 31, 1 };
    struct sol_irange hour = { 0, 0, 23, 1 };
    struct sol_irange min = { 0, 0, 59, 1 };
    struct sol_irange sec = { 0, 0, 59, 1 };
    struct sol_irange nsec = { 0, 0, 999999999, 1 };
    struct sol_irange wday = { 0, 0, 6, 1 };
    struct sol_irange yday = { 0, 0, 365, 1 };
    int r;

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

    tzset();
    if (!localtime_r(&value.tv_sec, &split_time)) {
        sol_flow_send_error_packet(node, EINVAL,
            "Could not convert time.");
        return 0;
    }

    year.val = split_time.tm_year + 1900;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__YEAR,
        &year);
    SOL_INT_CHECK(r, < 0, r);

    mon.val = split_time.tm_mon + 1;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MONTH,
        &mon);
    SOL_INT_CHECK(r, < 0, r);

    mday.val = split_time.tm_mday;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MONTH_DAY,
        &mday);
    SOL_INT_CHECK(r, < 0, r);

    hour.val = split_time.tm_hour;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__HOUR,
        &hour);
    SOL_INT_CHECK(r, < 0, r);

    min.val = split_time.tm_min;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MINUTE,
        &min);
    SOL_INT_CHECK(r, < 0, r);

    sec.val = split_time.tm_sec;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__SECOND,
        &sec);
    SOL_INT_CHECK(r, < 0, r);

    nsec.val = value.tv_nsec;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__NANO_SECOND,
        &nsec);
    SOL_INT_CHECK(r, < 0, r);

    wday.val = split_time.tm_wday;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__WEEK_DAY,
        &wday);
    SOL_INT_CHECK(r, < 0, r);

    yday.val = split_time.tm_yday;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__YEAR_DAY,
        &yday);
    SOL_INT_CHECK(r, < 0, r);

    if (split_time.tm_isdst < 0)
        SOL_DBG("Daylight saving time information not available.");
    else {
        r = sol_flow_send_boolean_packet(node,
            SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__DAYLIGHT_SAVING_TIME,
            !!split_time.tm_isdst);
        SOL_INT_CHECK(r, < 0, r);
    }

    return 0;
}
Beispiel #16
0
static int
not_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    int r;
    struct sol_irange in_value;
    struct sol_irange out_value = { .min = INT32_MIN, .step = 1, .max = INT32_MAX };

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    out_value.val = ~in_value.val;
    return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_BITWISE_NOT__OUT__OUT, &out_value);
}


// =============================================================================
// IRANGE COMPARISON
// =============================================================================

struct irange_comparison_data {
    bool (*func) (int32_t var0, int32_t var1);
    int32_t var0;
    int32_t var1;
    uint16_t port;
    bool var0_initialized : 1;
    bool var1_initialized : 1;
};

static bool
irange_val_equal(int32_t var0, int32_t var1)
{
    return var0 == var1;
}

static int
equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_EQUAL__OUT__OUT;
    mdata->func = irange_val_equal;

    return 0;
}

static bool
irange_val_less(int32_t var0, int32_t var1)
{
    return var0 < var1;
}

static int
less_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_LESS__OUT__OUT;
    mdata->func = irange_val_less;

    return 0;
}

static bool
irange_val_less_or_equal(int32_t var0, int32_t var1)
{
    return var0 <= var1;
}

static int
less_or_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_LESS_OR_EQUAL__OUT__OUT;
    mdata->func = irange_val_less_or_equal;

    return 0;
}

static bool
irange_val_greater(int32_t var0, int32_t var1)
{
    return var0 > var1;
}

static int
greater_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_GREATER__OUT__OUT;
    mdata->func = irange_val_greater;

    return 0;
}

static bool
irange_val_greater_or_equal(int32_t var0, int32_t var1)
{
    return var0 >= var1;
}

static int
greater_or_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_EQUAL__OUT__OUT;
    mdata->func = irange_val_greater_or_equal;

    return 0;
}

static bool
irange_val_not_equal(int32_t var0, int32_t var1)
{
    return var0 != var1;
}

static int
not_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_NOT_EQUAL__OUT__OUT;
    mdata->func = irange_val_not_equal;

    return 0;
}

static int
comparison_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;
    int r;
    struct sol_irange in_value;
    bool output;

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    if (port == 0) {
        mdata->var0_initialized = true;
        mdata->var0 = in_value.val;
    } else if (port == 1) {
        mdata->var1_initialized = true;
        mdata->var1 = in_value.val;
    }

    /* only send something after both variables values are received */
    if (!(mdata->var0_initialized && mdata->var1_initialized))
        return 0;

    output = mdata->func(mdata->var0, mdata->var1);

    return sol_flow_send_boolean_packet(node, mdata->port, output);
}

// =============================================================================
// IRANGE MAP
// =============================================================================


struct irange_map_data {
    struct sol_irange input;
    struct sol_irange output;
    struct sol_irange output_value;
    bool use_input_range : 1;
};

static int
irange_map_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_map_data *mdata = data;
    const struct sol_flow_node_type_int_map_options *opts;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_INT_MAP_OPTIONS_API_VERSION, -EINVAL);

    opts = (const struct sol_flow_node_type_int_map_options *)options;

    mdata->use_input_range = opts->use_input_range;

    mdata->input = opts->input_range;

    if (!mdata->use_input_range && (mdata->input.min >= mdata->input.max)) {
        SOL_WRN("Invalid range: input max must to be bigger than min");
        return -EINVAL;
    }

    mdata->output = opts->output_range;

    /* We allow output.min > output.max to invert range, but
     * when sending the packet, min and max must to be in correct
     * order */
    if (mdata->output.min < mdata->output.max) {
        mdata->output_value.min = mdata->output.min;
        mdata->output_value.max = mdata->output.max;
    } else {
        mdata->output_value.max = mdata->output.min;
        mdata->output_value.min = mdata->output.max;
    }

    if (opts->output_range.step < 1) {
        SOL_WRN("Output step need to be > 0");
        return -EDOM;
    }
    mdata->output_value.step = opts->output_range.step;

    return 0;
}

static int
_map(int64_t in_value, int64_t in_min, int64_t in_max, int64_t out_min, int64_t out_max, int64_t out_step, int32_t *out_value)
{
    int64_t result;

    if ((in_max - in_min) == out_min) {
        SOL_WRN("Input max - input min == output min");
        return -EDOM;
    }

    result = (in_value - in_min) * (out_max - out_min) /
             (in_max - in_min) + out_min;
    result -= (result - out_min) % out_step;
    *out_value = result;

    return 0;
}
Beispiel #17
0
static void
_tick(struct sol_flow_node *node)
{
    sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_CALAMARI_SEGMENTS_CTL__OUT__CLOCK, true);
    sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_CALAMARI_SEGMENTS_CTL__OUT__CLOCK, false);
}