I try to learn the protole radio. I have find the trame's format but the data on their modulation i find are confusing.
I look for info on :
what modulation is used by thes protocole
if more than one is used : in with case one is used
List of potocole and data i find:
bluetooth : V1=MSK / V2=DQPSK / low energy=GFSK(not sure)
wifi : PSK(hypothesis)
RFID : BPSK
Zigbee 868MHz: BPSK(not sure in if it's the only one)
domotic 868MHz : BPSK(hypothesis)
I'm trying to run my service with Micronaut and Cassandra (currently version 3.11.10) and store a column that is a set of tuples into Cassandra.
example code:
QueryBuilder
.insertInto(table)
.value("column", QueryBuilder.literal(items.map { it.toTuple() }.toSet())))
The toTuple() method is just an extension method that transfer the items into Term objects
When I'm doing so I'm receiving the following error:
Internal Server Error: Could not inline literal of type java.util.Collections$SingletonSet. This happens because the driver doesn't know how to map it to a CQL type. Try passing a TypeCodec or CodecRegistry to literal().
I've checked online in multiple sources but couldn't find a simple way to store a set of tuples into the database without implementing my custom TypeCodec. As I'm sure that I'm not the first person to have this issue, I'm probably doing something completely wrong, however I couldn't find any documentation regarding to what is the correct way of doing this.
Please forgive me, I don't even know if what I am asking is the correct terminology.
So...here goes.
I built a custom firmware of Nodemcu Dali ( from Hackerspace Stutgart.) This includes a dali lighting control "flavour" as they refer to. I had to modify it to work with the most recent LUA version. Anyway that works and the MODULE is built into the firmware.
From the LUA commandline / Interpretor (Esplorer interface, I can call the module and it all works fine.
To use the module you enter:
dali.arc(address_Mode,0,parameter)
or
dali.send(Address_Mode,Command,Address,parameter)
Address_mode can be: dali.SLAVE , dali.GROUP
Command can be dali.UP_200MS , dali.IMMEDIATE_OFF , dali.GO_TO_SCENE --... about 50 commands.
An Example command to send the light level 128 to all drivers would be as follows:
dali.arc(dali.BROADCAST,0,128) -- direct arc mode ( all lights,*ignored*,50% dimmed)
I want to use MQTT to control this thing.
I could use MQTT topics:
dali_topic/arc_broadcast -- for dali.arc(dali.BROADCAST,var1,var2)
dali_topic/group -- for dali.arc(dali.GROUP,var1,var2)
dali_topic/slave -- for dali.arc(dali.SLAVE,var1,var2)
and my payload string would only have to 2 variables,comma seperated eg. 0,128.
This I can all do day long but now I want to make it "better"...
I want to be able to rather send the message " dali.BROADCAST,0,128" which the code should then sort into a table with elements:
table[1] = dali.BROADCAST
table[2] = 0
table[3] = 128
and call dali.arc(table[1],table[2],table[3])
The table creation works,but I cannot get dali.BROADCAST passed to the module /function? call. First off because it is a string and second because it cannot be converted to a number or whatever substitute is required.
If this can be done them the Command field could aslo be sent with the MQTT payload rather than needing 50 MQTT topics.
I suppose I could also just try a lot of if statements or search a lookup table, but perhaps there is a simple way to just insert the command field in to function/module call?
Any assistance greatly appreciated
Edit here is some LUA output:
table ={"dali.BROADCAST",0,128}
dali.arc(table[1],table[2],table[3])
result:
Lua error: stdin:1: bad argument #1 to 'arc' (number expected, got boolean)
since if you print("dali.BROADCAST") you get nil
However
table[4] = dali.BROADCAST
dali.arc(table[4],table[2],table[3])
result works fine.
print( type(dali.BROADCAST ))
gives number
so how to pass my mqtt string dali.BROADCAST which is received as "dali.BROADCAST" and convert it to just dali.BROADCAST?
note I am not sending "" the message is however sent by MQTT as a CSV string.
From the Firmware source for the dali module.. in the module folder: dali.c
LROT_BEGIN(dali, NULL, 0)
LROT_FUNCENTRY( setup, dali_setup )
LROT_FUNCENTRY( arc, dali_arc )
LROT_FUNCENTRY( send, dali_send )
LROT_NUMENTRY( BROADCAST, BROADCAST )
LROT_NUMENTRY( SLAVE, SLAVE )
LROT_NUMENTRY( GROUP, GROUP )
LROT_NUMENTRY( IMMEDIATE_OFF, DALI_IMMEDIATE_OFF)
LROT_NUMENTRY( GO_TO_SCENE, DALI_GO_TO_SCENE)
The shackspace github link is the correct one, it is simply based on LUA1.45 or something low like that. I only had to modify dali.c in Modules to work with the lastest LUA.
The relevant dali files in the firmware is located in
app/modules
app/include
app/dali
folders
EDIT: Thinking about it, you probably always end up indexing dali, in which case you can do so directly by just structuring your table like this:
table[1] = "arc"
table[2] = "BROADCAST"
table[3] = 0
table[4] = 128
This way you can get to dali.BROADCAST by doing dali[table[2]] and to dali.arc by doing dali[table[1]].
HINT: You should probably still keep a whitelist of what is allowed where because someone could send any string and your program shouldn't just blindly index the dali table with that and return it.
You probably want something like this
Here's the relevant code:
function deepindex(tab, path)
if type(path)~="string" then
return nil, "path is not a string"
end
local index, rest = path:match("^%.?([%a%d]+)(.*)")
if not index then
index, rest = path:match("^%[(%d+)%](.*)")
index = tonumber(index)
end
if index then
if #rest>0 then
if tab[index] then
return deepindex(tab[index], rest)
else
return nil, "full path not present in table"
end
else
return tab[index]
end
else
return nil, "malformed index-path string"
end
end
Homework: this function also works with [] indexing for numbers, which you don't need. It should be easy to simplify the function to only do string-indexing with .
You would use that on the global environment to index it with a single string:
deepindex(_G, "dali.BROADCAST")
-- Which is the same as
_G.dali.BROADCAST
-- And, unless dali is a local, also
dali.BROADCAST
Keep in mind though, that this lets you remote-index _G with anything, which is a huge security nightmare. Better do this:
local whitelist = {}
whitelist.dali = dali
deepindex(whitelist, "dali.BROADCAST") -- this works
deepindex(whitelist, "some.evil.submodule") -- This does nothing
Was looking for a Wiki entry with more details, but I found none. If you happen to know where documentation is that specifies more about the available Lua commands, please include a link in your question.
It appears that there may be other functions to approach the same outcome, but I'm not certain how they are worded in your particular build.
https://github.com/shackspace/nodemcu-firmware-dali/blob/master/app/dali/dali_encode.c
What's returned when you print( type( dali.BROADCAST )) ?
I was guessing it might be raw C userdata, the specific case-switch for that arc command, however, I just found a similar Lua project that lists it as hexadecimal 255
https://github.com/a-lurker/Vera-Plugin-DALI-Planet/blob/master/Luup_device/L_DaliPlanet1.lua
Yea, it's likely just sending hexadecimal numbers.
https://en.wikipedia.org/wiki/Digital_Addressable_Lighting_Interface
try sending dali.arc( 0xFF, 0x00, 0x80 )
or dali.arc( 0xFE, 0x80 )
They make it sound like '1111 1110' ( 0xFE ) is directly followed by the brightness value, so that second command might light.
I'm not sure why it doesn't appear to be sending the correct codes when you place them in a table. What you've written appears to be correct, but it's likely a one-way broadcast, so you don't receive back any error messages...
If you can't get the arc command to work with tables, possibly you'll have better luck with the dali.send() command. Might just be a flaw in that app. If you can't get it resolved, submit a bug report to their GitHub page.
I ' ve some troubles , managing my i18n in my database
For now I ' just two languages available on my application , but in order to be scalable, I would like to do it the "best" way.
I could have duplicated all fields like description_fr, description_en but I was no confortable with this at all. What I've done for now, is a external table , call it content, and its architecture is like this :
id_ref => entity referenced id (2)
type => table name (university)
field => field of the specific table (description)
lang => which lang (fr, en, es…)
content => and finally the appropriate content.
I think it can be important to precise, I use sequelizeJS as ORM. So I can use a usefull hooks as afterFind, afterCreate and afterUpdate. So Each time I wanna to find a resource for example, after find it, my hook retrieve all content for this resource and set definitly my object with goods values. It works, but I'm not in love with this.
But I have some troubles with this :
It's increase considerably my number of requests to the database : If I select 50 rows for example, I have to do 50 requests more.. , and just for a particular model. If I have nested models, it's exponential…
Then, It's complicated to fetch data by content i18ned. Example find a university with a specific name is complicated.
And It's a lot of work for updating etc...
So I wonder, if it would be a good idea , to save as a JSON, directly in the table concerned , the data. Something like
{
fr : { 'name':'Ma super université' },
en : { 'name':'My kick ass university' }
}
And keep on using Sequelize Hooks to build and insert proper data into my object.
What do you think ?
How do you manage this ?
EDIT
I use a mysql database
It concerns around 20 fields (cross models)
I have to set the default value using a my default_lang if there is no content set (e.g, event.description in french will be the same as the english one, if there is no content set)
I used this npm package sequelize-i18n. It worked pretty fine for me using sequelize 3.23.2, unfortunately it seems does not have support for sequelize 4.x yet.
A VERY nice to have would be if I could edit object-literals in this editor's text-field instead of JSON expressions.
If I could replace the JSON parse with a simple eval - it will make editing sooooo much easier! (and help me design document structures for my projects soooo much more easily)
I mean, gosh!! it's not a protocol school, it's an editor's tool.
The goal of the tool is not to teach me the protocol and comment me on every petty mistake, but to help me design documents for the software.
Why must it ensist on strict JSON? Can't it live with Object Literals, and do for us the
JSON.stringify( eval(editor_textarea.value))
woulnd't that be cool? LOL :D
(yea yea, catching errors and feeding back to the user)
(and for who ever missed the difference - it is mainly in the quote marks in attribute names.
the dry strict JSON protocol require quotemarks ALWAYS, no question asked, where JS object literal require quote-marks only for attribute names that are not legal JS variable names and accepts also numbers without quotation marks)
Strict dry JSON:
{ "attribute" : "value"
, "mapmap" :
{ "map" :
{ "attr" : "sdss"
, "123" : "ss32332"
, "val" : 23323
, "456" : "ss32332"
}
}
}
Object Literal
{ attribute: "value"
, mapmap :
{ map :
{ attr : "sdss"
, 123 : "ss32332"
, val : 23323
, 456 : "ss32332"
}
}
}
Well, it won't solve me missing commas or mismatching brakets, but it does make life easier, where quote marks are a big part of the scaffold.
If you can point me to where I can change this even as patch on the futon I'll be soooOOO greatful :)
Maybe later we can integrate there an editor helper such as the cool one in github source-editor or the one in jsfiddle, that helps you indent and color things nicely.
But lets start with a simple eval.
it will make life easier... :)
It can also let me generate complicated documents using JS code without any additional test software...
Happy coding :)
P.S
If you know the answer here - you might know the answer to this question:
couchdb futon document editor - can I customize the indentation rules?
I had a quick browse, and I believe this is where you will want to add your eval:
https://github.com/apache/couchdb/blob/master/share/www/script/futon.browse.js#L911
and here:
https://github.com/apache/couchdb/blob/master/share/www/script/futon.browse.js#L902
You can edit your local couchdb instance share/www/script/futon.browse.js if you want to see live changes.