Related
Working with InfluxDB is new for me. My problem is I have two measurements (StopCause and MachineState). Both have some objects inside. I wanna join from MachineState to StopCause with join.left. I check the timestamp (Flux's standard _timeobject). But the result gives me not the "relation object" (so to say) what I hope to see.
First the sturctures of the objects:
StopCause
{
_start: '2023-02-09T10:00:00Z',
_stop: '2023-02-09T13:00:00Z',
_time: '2023-02-09T11:00:00Z',
_value: 100002,
_field: 'stopCauseId',
_measurement: 'StopCause',
eventId: '"267e2cab-fd2d-4684-a5fc-7792368115b3"',
machine: '5000002_dev'
},
MachineState
{
_start: '2023-02-09T10:00:00Z',
_stop: '2023-02-09T13:00:00Z',
_time: '2023-02-09T11:00:00Z',
_value: 1,
_field: 'state',
_measurement: 'MachineState',
machine: '5000002_dev'
},
You see the _time object is absolutely the same. I insert data with manually set the timestamp.
Here is the query:
*Note: I working with NodeJS and the official #influxdata/influxdb-client package. The ${VALUE} things are Javascript variables.
${dateFrom.toISOString()} = 2023-02-09T10:00:00Z
${dateTo.toISOString()} = 2023-02-09T13:00:00Z
${externalAssetId} = 5000002_dev
import "join"
import "contrib/tomhollingworth/events"
t1 = from(bucket: "Downtime_OEE")
|> range(start: ${dateFrom.toISOString()}, stop: ${dateTo.toISOString()})
|> filter(fn: (r) => r["_measurement"] == "MachineState")
|> filter(fn: (r) => r["machine"] == "${externalAssetId}")
|> group(columns: ["_time"])
t2 = from(bucket: "Downtime_OEE")
|> range(start: ${dateFrom.toISOString()}, stop: ${dateTo.toISOString()})
|> filter(fn: (r) => r["_measurement"] == "StopCause")
|> filter(fn: (r) => r["machine"] == "${externalAssetId}")
|> pivot(rowKey:["_time","eventId","machine"], columnKey: ["_field"], valueColumn: "_value")
join.left(
left: t1,
right: t2,
on: (l, r) => l._time == r._time,
as: (l, r) => {
id = if exists r.eventId then r.eventId else "Nothing"
return {_time: l._time, otime: r._time, start: l._start, eventId: id}},
)
What I expect to have:
{
result: '_result',
table: 1,
_time: '2023-02-09T11:00:00Z',
eventId: 'xyz-123456',
otime: '2023-02-09T11:00:00Z',
start: '2023-02-09T10:00:00Z'
}
What I get:
{
result: '_result',
table: 1,
_time: '2023-02-09T11:00:00Z',
eventId: 'Nothing',
otime: '2023-02-09T11:00:00Z',
start: '2023-02-09T10:00:00Z'
}
So... how do I join correctly to get the eventId?
I am receiving the below error when trying to compile the device_handler code for the Sylvania Smart+ Plug. The code comes from https://images-na.ssl-images-amazon.com/images/I/71PrgM-PamL.pdf
The error:
Org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: script_dth_metadata_0631e407_ffd8_4ceb_b49a_877fd47635df: 94: expecting ''', found '\r' # line 94, column 55. nalResult.value == "on" ? '{{ ^ 1 error
Line 94:
def descriptionText = finalResult.value == "on" ? '{{
metadata {
definition (name: "SYLVANIA Smart Plug", namespace: "ledvanceDH", author:
"Ledvance") {
capability "Actuator"
capability "Switch"
capability "Power Meter"
capability "Configuration"
capability "Refresh"
capability "Sensor"
capability "Health Check"
fingerprint profileId: "C05E", inClusters:
"1000,0000,0003,0004,0005,0006,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM",
model: "Plug 01", deviceJoinName: "SYLVANIA Smart Plug"
fingerprint profileId: "0104", inClusters:
"0000,0003,0004,0005,0006,0B05,FC01,FC08", outClusters: "0003,0019", manufacturer:
"LEDVACE", model: "PLUG", deviceJoinName: "SYLVANIA Smart Plug"
}
// simulator metadata
simulator {
// status messages
status "on": "on/off: 1"
status "off": "on/off: 0"
// reply messages
reply "zcl on-off on": "on/off: 1"
reply "zcl on-off off": "on/off: 0"
}
preferences {
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.devicegse.smartthings.com/Outlet/US/OutletUS1.jpg",
"http://cdn.devicegse.smartthings.com/Outlet/US/OutletUS2.jpg"
])
}
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4,
canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: 'On', action: "switch.off",
icon: "st.Appliances.appliances17", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "off", label: 'Off', action: "switch.on",
icon: "st.Appliances.appliances17", backgroundColor: "#565C51", nextState: "turningOn"
attributeState "turningOn", label: 'Turning On', action:
"switch.off", icon: "st.Appliances.appliances17", backgroundColor: "#60903A", nextState:
"turningOff"
attributeState "turningOff", label: 'Turning Off', action:
"switch.on", icon: "st.Appliances.appliances17", backgroundColor: "#CACACA", nextState:
"turningOn"
}
tileAttribute ("power", key: "SECONDARY_CONTROL") {
attributeState "power", label:'${currentValue} W'
}
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration:
"flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh",
icon:"st.secondary.refresh"
}
main "switch"
details(["switch","refresh"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def finalResult = zigbee.getKnownDescription(description)
def event = [:]
//TODO: Remove this after getKnownDescription can parse it automatically
if (!finalResult && description!="updated")
finalResult =
getPowerDescription(zigbee.parseDescriptionAsMap(description))
if (finalResult) {
log.info "final result = $finalResult"
if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}"
event = null
}
else if (finalResult.type == "power") {
def powerValue = (finalResult.value as Integer)/10
event = createEvent(name: "power", value: powerValue,
descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable:
true)
/*
Dividing by 10 as the Divisor is 10000 and unit is kW for
the device. AttrId: 0302 and 0300. Simplifying to 10
power level is an integer. The exact power level with
correct units needs to be handled in the device type
to account for the different Divisor value (AttrId: 0302)
and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702
*/
}
else {
def descriptionText = finalResult.value == "on" ? '{{
device.displayName }} is On' : '{{ device.displayName }} is Off'
event = createEvent(name: finalResult.type, value:
finalResult.value, descriptionText: descriptionText, translatable: true)
}
}
else {
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07){
if (cluster.data[0] == 0x00) {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
event = createEvent(name: "checkInterval", value: 60 * 12,
displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error
code:${cluster.data[0]}"
event = null
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
}
}
return event
}
def off() {
zigbee.off()
}
def on() {
zigbee.on()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.electricMeasurementPowerRefresh()
}
def configure() {
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false,
data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no
activity
refresh() + zigbee.onOffConfig(0, 300) + powerConfig()
}
//power config for devices with min reporting interval as 1 seconds and reporting
interval if no activity as 10min (600s)
//min change in value is 01
def powerConfig() {
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04
{${device.zigbeeId}} {}", "delay 2000",
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}",
//The send-me-a-report is custom to the attribute type for CentraLite
"delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
//TODO: Remove this after getKnownDescription can parse it automatically
def getPowerDescription(descMap) {
def powerValue = "undefined"
if (descMap.cluster == "0B04") {
if (descMap.attrId == "050b") {
if(descMap.value!="ffff")
powerValue = zigbee.convertHexToInt(descMap.value)
}
}
else if (descMap.clusterId == "0B04") {
if(descMap.command=="07"){
return [type: "update", value : "power (0B04) capability configured
successfully"]
}
}
if (powerValue != "undefined"){
return [type: "power", value : powerValue]
}
else {
return [:]
}
}
I should have thought of it sooner... The problem is with the copy/paste. The long lines were broken by a "return". I removed the returns and the script compiled.
hi I am trying to understand issue where given if (version_exists != '' && env.force_build == true) is evaluating to true even if env.force_build is set to false
pipeline {
agent { label 'master' }
parameters {
string(defaultValue: 'DEV', description: '', name: 'ENV', trim: true)
string(defaultValue: 'sys', description: '', name: 'platform_type', trim: true)
string(defaultValue: 'yyy', description: '', name: 'dev_app_host', trim: true)
string(defaultValue: 'xxx.dv.local', description: '', name: 'dev_xbar_host', trim: true)
string(defaultValue: '1.0.0.23', description: '', name: 'VERSION', trim: true)
booleanParam(defaultValue: false, description: 'force build if possible', name: 'force_build')
}
environment {
git_credential_id = '1234'
app_name = 'application'
app_module_name = 'dvmt_event_processor'
app_git_url = 'ssh://git#oooo:7999/data/application.git'
dna_common_git_url = 'ssh://git#oooo:7999/data/dna-common.git'
ansible_git_url = 'ssh://git#oooo:7999/data/operations-ansible.git'
pip_port = '9700'
}
stages {
stage('checkout from SCM') {
.....
}
stage('build') {
steps {
script {
// version_exists == dvmt_event_processor-1.0.0.23-py2.py3-none-any.whl
// force_build == false
def version_exists = ''
version_exists = sh(script: "ssh -o StrictHostKeyChecking=no ansible#pypi server ls /var/pypi/packages/dev/ | grep ${env.app_module_name} | grep ${env.VERSION}" , returnStdout: true)
if (version_exists != '' && env.force_build == true) {
......
// evaluating to true no matter what
}
}
else if (version_exists != '' && env.force_build == false ) {
echo "version already exists, just deploying"
......
}
else {
echo "starting full build"
.........
}
}
}
}
stage('Test') {
steps {
echo 'Testing...'
.............
}
}
}
}
jenkins console o/p
dvmt_event_processor-1.0.0.23-py2.py3-none-any.whl
[Pipeline] echo
false
[Pipeline] echo
starting full build
env.force_build prints like a boolean, but it is a string.
"false" == true
// → false
"false" == false
// → false
Always debug problems like this with the proper tools. Use .inspect()
or even .dump() to get insights, what kind of data you have at hand:
"false".inspect()
// → 'false'
"false".dump()
// → <java.lang.String#5cb1923 value=[102, 97, 108, 115, 101] coder=0 hash=97196323>
Note the quotes around false with the .inspect() example.
To convert a string to boolean with groovy, you can use
String.toBoolean():
"false".toBoolean() == true
// → false
"false".toBoolean() == false
// → true
I'm generating a dynamic update query based on a list of provided objects for postgres. This is what my query looks like:
update loan_item_assignment as t set id = c.id, dateselectionid = c.dateselectionid, loanitemid = c.loanitemid, active = c.active, type = c.type from (values ( $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 ) ) as c( id, dateselectionid, loanitemid, active, type ) where c.id = t.id returning *
And here's the values list I'm giving it:
[ 7,
35,
3,
true,
'normal',
8,
35,
4,
true,
'normal',
1,
35,
6,
true,
'normal',
2,
35,
7,
true,
'normal',
3,
35,
8,
true,
'normal',
5,
35,
10,
true,
'normal',
4,
35,
11,
true,
'normal',
6,
35,
12,
true,
'normal' ]
As far as I can tell, the values match up correctly. This is the error I'm seeing:
{ [error: operator does not exist: text = integer]
name: 'error',
length: 195,
severity: 'ERROR',
code: '42883',
detail: undefined,
hint: 'No operator matches the given name and argument type(s). You might need to add explicit type casts.',
position: '448',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'parse_oper.c',
line: '726',
routine: 'op_error' }
And this is the code that's ultimately running the query:
var performQuery = function(text, values, cb) {
pg.connect(connectionString, function(err, client, done) {
client.query(text, values, function(err, result) {
done();
if (!result) {
console.log(err);
cb([], err);
} else {
cb(result.rows, err);
}
})
});
}
And here is the table definition:
Table "public.loan_item_assignment"
Column | Type | Modifiers | Storage | Stats target | Description
-----------------+---------+-------------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('loan_item_assignment_id_seq'::regclass) | plain | |
dateselectionid | integer | | plain | |
loanitemid | integer | | plain | |
active | boolean | | plain | |
type | text | | extended | |
Indexes:
"loan_item_assignment_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"loan_item_assignment_dateselectionid_fkey" FOREIGN KEY (dateselectionid) REFERENCES date_selection(id)
"loan_item_assignment_loanitemid_fkey" FOREIGN KEY (loanitemid) REFERENCES loan_item(id)
Vitaly-t's comment on my answer is the solution - to use the pg-promise library to generate the query, and specifically method helpers.update for generating multi-row update queries, as shown in PostgreSQL multi-row updates in Node.js.
I am using the nagios to monitor gearman and getting error "CRITICAL - function 'xxx' is not registered in the server"
Script that nagios execute to check the gearman is like
#!/usr/bin/env perl
# taken from: gearmand-0.24/libgearman-server/server.c:974
# function->function_name, function->job_total,
# function->job_running, function->worker_count);
#
# this code give following result with gearadmin --status
#
# FunctionName job_total job_running worker_count
# AdsUpdateCountersFunction 0 0 4
use strict;
use warnings;
use Nagios::Plugin;
my $VERSION="0.2.1";
my $np;
$np = Nagios::Plugin->new(usage => "Usage: %s -f|--flist <func1[:threshold1],..,funcN[:thresholdN]> [--host|-H <host>] [--port|-p <port>] [ -c|--critworkers=<threshold> ] [ -w|--warnworkers=<threshold>] [-?|--usage] [-V|--version] [-h|--help] [-v|--verbose] [-t|--timeout=<timeout>]",
version => $VERSION,
blurb => 'This plugin checks a gearman job server, expecting that every function in function-list arg is registered by at least one worker, and expecting that job_total is not too much high.',
license => "Brought to you AS IS, WITHOUT WARRANTY, under GPL. (C) Remi Paulmier <remi.paulmier\#gmail.com>",
shortname => "CHECK_GEARMAN",
);
$np->add_arg(spec => 'flist|f=s',
help => q(Check for the functions listed in STRING, separated by comma. If optional threshold is given (separated by :), check that waiting jobs for this particular function are not exceeding that value),
required => 1,
);
$np->add_arg(spec => 'host|H=s',
help => q(Check the host indicated in STRING),
required => 0,
default => 'localhost',
);
$np->add_arg(spec => 'port|p=i',
help => q(Use the TCP port indicated in INTEGER),
required => 0,
default => 4730,
);
$np->add_arg(spec => 'critworkers|c=i',
help => q(Exit with CRITICAL status if fewer than INTEGER workers have registered a particular function),
required => 0,
default => 1,
);
$np->add_arg(spec => 'warnworkers|w=i',
help => q(Exit with WARNING status if fewer than INTEGER workers have registered a particular function),
required => 0,
default => 4,
);
$np->getopts;
my $ng = $np->opts;
# manage timeout
alarm $ng->timeout;
my $runtime = {'status' => OK,
'message' => "Everything OK",
};
# host & port
my $host = $ng->get('host');
my $port = $ng->get('port');
# verbosity
my $verbose = $ng->get('verbose');# look for gearadmin, use nc if not found
my #paths = grep { -x "$_/gearadmin" } split /:/, $ENV{PATH};
my $cmd = "gearadmin --status -h $host -p $port";
if (#paths == 0) {
print STDERR "gearadmin not found, using nc\n" if ($verbose != 0);
# $cmd = "echo status | nc -w 1 $host $port";
$cmd = "echo status | nc -i 1 -w 1 $host $port";
}
foreach (`$cmd 2>/dev/null | grep -v '^\\.'`) {
chomp;
my ($fname, $job_total, $job_running, $worker_count) =
split /[[:space:]]+/;
$runtime->{'funcs'}{"$fname"} = {job_total => $job_total,
job_running => $job_running,
worker_count => $worker_count };
# print "$fname : $runtime->{'funcs'}{\"$fname\"}{'worker_count'}\n";
}
# get function list
my #flist = split /,/, $ng->get('flist');
foreach (#flist) {
my ($fname, $fthreshold);
if (/\:/) {
($fname, $fthreshold) = split /:/;
} else {
($fname, $fthreshold) = ($_, -1);
}
# print "defined for $fname: $runtime->{'funcs'}{\"$fname\"}{'worker_count'}\n";
# if (defined($runtime->{'funcs'}{"$fname"})) {
# print "$fname is defined\n";
# } else {
# print "$fname is NOT defined\n";
# }
if (!defined($runtime->{'funcs'}{"$fname"}) &&
$runtime->{'status'} <= CRITICAL) {
($runtime->{'status'}, $runtime->{'message'}) =
(CRITICAL, "function '$fname' is not registered in the server");
} else {
if ($runtime->{'funcs'}{"$fname"}{'worker_count'} <
$ng->get('critworkers') && $runtime->{'status'} <= CRITICAL) {
($runtime->{'status'}, $runtime->{'message'}) =
(CRITICAL,
"less than " .$ng->get('critworkers').
" workers were found having function '$fname' registered.");
}
if ($runtime->{'funcs'}{"$fname"}{'worker_count'} <
$ng->get('warnworkers') && $runtime->{'status'} <= WARNING) {
($runtime->{'status'}, $runtime->{'message'}) =
(WARNING,
"less than " .$ng->get('warnworkers').
" workers were found having function '$fname' registered.");
}
if ($runtime->{'funcs'}{"$fname"}{'job_total'} > $fthreshold
&& $fthreshold != -1 && $runtime->{'status'}<=WARNING) {
($runtime->{'status'}, $runtime->{'message'}) =
(WARNING,
$runtime->{'funcs'}{"$fname"}{'job_total'}.
" jobs for $fname exceeds threshold $fthreshold");
}
}
}
$np->nagios_exit($runtime->{'status'}, $runtime->{'message'});
When the script is executed simply by command line it says "everything ok"
But in nagios it shows error "CRITICAL - function 'xxx' is not registered in the server"
Thanks in advance
After spending long time on this, finally got the answer all that have to do is.
yum install nc
nc is what that was missing from the system.
With Regards,
Bankat Vikhe
Not easy to say but it could be related to your script not being executable as embedded Perl.
Try with # nagios: -epn at the beginning of the script.
#!/usr/bin/env perl
# nagios: -epn
use strict;
use warnings;
Be sure to check all the hints in the Perl Plugins section of the Nagios Plugin Development Guidelines