| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736 |
- ##############################################
- # $Id: 00_SIGNALduino.pm 13215 2017-01-23 20:09:44Z Sidey $
- #
- # v3.3.1 (release 3.3)
- # The module is inspired by the FHEMduino project and modified in serval ways for processing the incomming messages
- # see http://www.fhemwiki.de/wiki/SIGNALDuino
- # It was modified also to provide support for raw message handling which can be send from the SIGNALduino
- # The purpos is to use it as addition to the SIGNALduino which runs on an arduno nano or arduino uno.
- # It routes Messages serval Modules which are already integrated in FHEM. But there are also modules which comes with it.
- # N. Butzek, S. Butzek, 2014-2015
- # S.Butzek,Ralf9 2016-2017
- package main;
- use strict;
- use warnings;
- use Time::HiRes qw(gettimeofday);
- use Data::Dumper qw(Dumper);
- use Scalar::Util qw(looks_like_number);
- no warnings 'portable';
- #use POSIX qw( floor); # can be removed
- #use Math::Round qw();
- use constant {
- SDUINO_VERSION => "v3.3.1",
- SDUINO_INIT_WAIT_XQ => 1.5, # wait disable device
- SDUINO_INIT_WAIT => 2,
- SDUINO_INIT_MAXRETRY => 3,
- SDUINO_CMD_TIMEOUT => 10,
- SDUINO_KEEPALIVE_TIMEOUT => 60,
- SDUINO_KEEPALIVE_MAXRETRY => 3,
- SDUINO_WRITEQUEUE_NEXT => 0.3,
- SDUINO_WRITEQUEUE_TIMEOUT => 2,
- };
- sub SIGNALduino_Attr(@);
- #sub SIGNALduino_Clear($); # wird nicht mehr benoetigt
- sub SIGNALduino_HandleWriteQueue($);
- sub SIGNALduino_Parse($$$$@);
- sub SIGNALduino_Read($);
- #sub SIGNALduino_ReadAnswer($$$$); # wird nicht mehr benoetigt
- sub SIGNALduino_Ready($);
- sub SIGNALduino_Write($$$);
- sub SIGNALduino_SimpleWrite(@);
- #my $debug=0;
- my %gets = ( # Name, Data to send to the SIGNALduino, Regexp for the answer
- "version" => ["V", 'V\s.*SIGNAL(duino|ESP).*'],
- "freeram" => ["R", '^[0-9]+'],
- "raw" => ["", '.*'],
- "uptime" => ["t", '^[0-9]+' ],
- "cmds" => ["?", '.*Use one of[ 0-9A-Za-z]+[\r\n]*$' ],
- "ITParms" => ["ip",'.*'],
- "ping" => ["P",'^OK$'],
- "config" => ["CG",'^MS.*MU.*MC.*'],
- "protocolIDs" => ["none",'none'],
- # "ITClock" => ["ic", '\d+'],
- # "FAParms" => ["fp", '.*' ],
- # "TCParms" => ["dp", '.*' ],
- # "HXParms" => ["hp", '.*' ]
- );
- my %sets = (
- "raw" => '',
- "flash" => '',
- "reset" => 'noArg',
- "close" => 'noArg',
- #"disablereceiver" => "",
- "ITClock" => 'slider,100,20,700',
- "enableMessagetype" => 'syncedMS,unsyncedMU,manchesterMC',
- "disableMessagetype" => 'syncedMS,unsyncedMU,manchesterMC',
- 'sendMsg' => "",
- );
- ## Supported Clients per default
- my $clientsSIGNALduino = ":IT:"
- ."CUL_TCM97001:"
- # ."SIGNALduino_RSL:"
- ."OREGON:"
- ."CUL_TX:"
- # ."SD_AS:"
- ."Hideki:"
- ."SD_WS07:"
- ."SD_WS09:"
- ." :" # Zeilenumbruch
- ."SD_WS:"
- ."RFXX10REC:"
- ."Dooya:"
- ."SOMFY:"
- # ."SD_UT:" ## BELL 201.2 TXA
- ."SD_WS_Maverick:"
- ."SIGNALduino_un:"
- ;
- ## default regex match List for dispatching message to logical modules, can be updated during runtime because it is referenced
- my %matchListSIGNALduino = (
- "1:IT" => "^i......", # Intertechno Format
- "2:CUL_TCM97001" => "^s[A-Fa-f0-9]+", # Any hex string beginning with s
- # "3:SIGNALduino_RSL" => "^r[A-Fa-f0-9]+", # Any hex string beginning with r
- "5:CUL_TX" => "^TX..........", # Need TX to avoid FHTTK
- # "6:SD_AS" => "^P2#[A-Fa-f0-9]{7,8}", # Arduino based Sensors, should not be default
- "4:OREGON" => "^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*",
- "7:Hideki" => "^P12#75[A-F0-9]+",
- "10:SD_WS07" => "^P7#[A-Fa-f0-9]{6}F[A-Fa-f0-9]{2}",
- "11:SD_WS09" => "^P9#[A-Fa-f0-9]+",
- "12:SD_WS" => '^W\d+x{0,1}#.*',
- "13:RFXX10REC" => '^(20|29)[A-Fa-f0-9]+',
- "14:Dooya" => '^P16#[A-Fa-f0-9]+',
- "15:SOMFY" => '^YsA[0-9A-F]+',
- "16:SD_WS_Maverick" => '^P47#[A-Fa-f0-9]+',
- # "17:SD_UT" => '^u30#.*', ## BELL 201.2 TXA
- "X:SIGNALduino_un" => '^[uP]\d+#.*',
- );
- my %ProtocolListSIGNALduino = (
- "0" =>
- {
- name => 'weather1', # Logilink, NC, WS, TCM97001 etc.
- comment => 'Logilink, NC, WS, TCM97001 etc',
- id => '0',
- one => [1,-8],
- zero => [1,-4],
- sync => [1,-18],
- clockabs => '500', # not used now
- format => 'twostate', # not used now
- preamble => 's', # prepend to converted message
- postamble => '00', # Append to converted message
- clientmodule => 'CUL_TCM97001', # not used now
- #modulematch => '^s[A-Fa-f0-9]+', # not used now
- length_min => '24',
- length_max => '40',
- paddingbits => '8', # pad up to 8 bits, default is 4
- },
- "1" =>
- {
- name => 'ConradRSL', #
- id => '1',
- one => [2,-1],
- zero => [1,-2],
- sync => [1,-11],
- clockabs => '560', # not used now
- format => 'twostate', # not used now
- preamble => 'r', # prepend to converted message
- postamble => '', # Append to converted message
- clientmodule => 'SIGNALduino_RSL', # not used now
- modulematch => '^r[A-Fa-f0-9]+', # not used now
- length_min => '23',
- length_max => '24',
- },
- "2" =>
- {
- name => 'AS', # Self build arduino sensor
- comment => 'Self build arduino sensor',
- id => '2',
- one => [1,-2],
- zero => [1,-1],
- sync => [1,-20],
- clockabs => '500', # not used now
- format => 'twostate',
- preamble => 'P2#', # prepend to converted message
- clientmodule => 'SD_AS', # not used now
- modulematch => '^P2#.{7,8}',
- length_min => '32',
- length_max => '34', # Don't know maximal lenth of a valid message
- paddingbits => '8', # pad up to 8 bits, default is 4
-
- },
- "3" =>
- {
- name => 'itv1',
- id => '3',
- one => [3,-1],
- zero => [1,-3],
- #float => [-1,3], # not full supported now later use
- sync => [1,-31],
- clockabs => -1, # -1=auto
- format => 'twostate', # not used now
- preamble => 'i',
- clientmodule => 'IT', # not used now
- modulematch => '^i......', # not used now
- length_min => '24',
- #length_max => '800', # Don't know maximal lenth of a valid message
- },
- "4" =>
- {
- name => 'arctech2',
- id => '4',
- #one => [1,-5,1,-1],
- #zero => [1,-1,1,-5],
- one => [1,-5],
- zero => [1,-1],
- #float => [-1,3], # not full supported now, for later use
- sync => [1,-14],
- clockabs => -1, # -1 = auto
- format => 'twostate', # tristate can't be migrated from bin into hex!
- preamble => 'i', # Append to converted message
- postamble => '00', # Append to converted message
- clientmodule => 'IT', # not used now
- modulematch => '^i......', # not used now
- length_min => '32',
- #length_max => '76', # Don't know maximal lenth of a valid message
- },
- "5" => ## Similar protocol as intertechno, but without sync
- {
- name => 'unitec6899',
- id => '5',
- one => [3,-1],
- zero => [1,-3],
- clockabs => 500, # -1 = auto
- format => 'twostate', # tristate can't be migrated from bin into hex!
- preamble => 'p5#', # Append to converted message
- clientmodule => 'IT', # not used now
- modulematch => '^i......', # not used now
- length_min => '24',
- },
-
- "6" => ## Eurochron Protocol
- {
- name => 'weatherID6',
- id => '6',
- one => [1,-10],
- zero => [1,-5],
- sync => [1,-36], # This special device has no sync
- clockabs => 220, # -1 = auto
- format => 'twostate', # tristate can't be migrated from bin into hex!
- preamble => 'u6#', # Append to converted message
- #clientmodule => '', # not used now
- #modulematch => '^u......', # not used now
- length_min => '24',
- },
- "7" => ## weather sensors like EAS800z
- {
- name => 'weatherID7',
- comment => 'EAS800z, FreeTec NC-7344',
- id => '7',
- one => [1,-4],
- zero => [1,-2],
- sync => [1,-8],
- clockabs => 484,
- format => 'twostate',
- preamble => 'P7#', # prepend to converted message
- clientmodule => 'SD_WS07', # not used now
- modulematch => '^P7#.{6}F.{2}', # not used now
- length_min => '35',
- length_max => '40',
- },
- "8" => ## TX3 (ITTX) Protocol
- {
- name => 'TX3 Protocol',
- id => '8',
- one => [1,-2],
- zero => [2,-2],
- #sync => [1,-8], #
- clockabs => 470, #
- format => 'pwm', #
- preamble => 'TX', # prepend to converted message
- clientmodule => 'CUL_TX', # not used now
- modulematch => '^TX......', # not used now
- length_min => '43',
- length_max => '44',
- remove_zero => 1, # Removes leading zeros from output
- },
- "9" => ## Funk Wetterstation CTW600
- {
- name => 'CTW 600',
- comment => 'Funk Wetterstation CTW600',
- id => '9',
- zero => [3,-2],
- one => [1,-2],
- #float => [-1,3], # not full supported now, for later use
- #sync => [1,-8], #
- clockabs => 480, # -1 = auto undef=noclock
- format => 'pwm', # tristate can't be migrated from bin into hex!
- preamble => 'P9#', # prepend to converted message
- clientmodule => 'SD_WS09', # not used now
- #modulematch => '^u9#.....', # not used now
- length_min => '70',
- length_max => '120',
- },
- "10" => ## Oregon Scientific 2
- {
- name => 'OSV2o3',
- id => '10',
- clockrange => [300,520], # min , max
- format => 'manchester', # tristate can't be migrated from bin into hex!
- clientmodule => 'OREGON',
- modulematch => '^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*',
- length_min => '64',
- length_max => '220',
- method => \&SIGNALduino_OSV2, # Call to process this message
- polarity => 'invert',
- },
- "11" => ## Arduino Sensor
- {
- name => 'AS',
- id => '11',
- clockrange => [380,425], # min , max
- format => 'manchester', # tristate can't be migrated from bin into hex!
- preamble => 'P2#', # prepend to converted message
- clientmodule => 'SD_AS', # not used now
- modulematch => '^P2#.{7,8}',
- length_min => '52',
- length_max => '56',
- method => \&SIGNALduino_AS # Call to process this message
- },
- "12" => ## hideki
- {
- name => 'Hideki protocol',
- id => '12',
- clockrange => [420,510], # min, max better for Bresser Sensors, OK for hideki/Hideki/TFA too
- format => 'manchester',
- preamble => 'P12#', # prepend to converted message
- clientmodule => 'hideki', # not used now
- modulematch => '^P12#75.+', # not used now
- length_min => '72',
- length_max => '104',
- method => \&SIGNALduino_Hideki, # Call to process this message
- polarity => 'invert',
-
- },
- "13" => ## FA21RF
- {
- name => '21RF',
- id => '13',
- one => [1,-2],
- zero => [1,-4],
- sync => [10,-1],
- clockabs => 800,
- format => 'twostate',
- preamble => 'u13#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '20',
- length_max => '40',
- },
- "14" => ## Heidemann HX
- {
- name => 'Heidemann HX',
- id => '14',
- one => [1,-2],
- zero => [1,-1],
- #float => [-1,3], # not full supported now, for later use
- sync => [1,-14], #
- clockabs => 350,
- format => 'twostate',
- preamble => 'u14#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '10',
- length_max => '20',
- },
- "15" => ## TCM234759
- {
- name => 'TCM Bell',
- id => '15',
- one => [1,-1],
- zero => [1,-2],
- sync => [1,-45], #
- clockabs => 700,
- format => 'twostate',
- preamble => 'u15#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '10',
- length_max => '20',
- #method => \&SIGNALduino_Cresta # Call to process this message
- },
- "16" => # Rohrmotor24 und andere Funk Rolladen / Markisen Motoren
- {
- name => 'Dooya shutter',
- id => '16',
- one => [2,-1],
- zero => [1,-3],
- start => [17,-5],
- clockabs => 280,
- format => 'twostate',
- preamble => 'P16#', # prepend to converted message
- clientmodule => 'Dooya', # not used now
- #modulematch => '', # not used now
- length_min => '39',
- length_max => '40',
- },
- "17" =>
- {
- name => 'arctech',
- id => '17',
- one => [1,-5,1,-1],
- zero => [1,-1,1,-5],
- #one => [1,-5],
- #zero => [1,-1],
- sync => [1,-10],
- float => [1,-1,1,-1],
- clockabs => -1, # -1 = auto
- format => 'twostate', # tristate can't be migrated from bin into hex!
- preamble => 'i', # Append to converted message
- postamble => '00', # Append to converted message
- clientmodule => 'IT', # not used now
- modulematch => '^i......', # not used now
- length_min => '32',
- #length_max => '76', # Don't know maximal lenth of a valid message
- postDemodulation => \&SIGNALduino_bit2Arctec,
- },
-
- "18" => ## Oregon Scientific v1
- {
- name => 'OSV1',
- id => '18',
- clockrange => [1550,1650], # min , max
- format => 'manchester', # tristate can't be migrated from bin into hex!
- #preamble => '', # prepend to converted message
- #clientmodule => 'to be written', # not used now
- modulematch => '^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*',
- length_min => '8',
- length_max => '8',
- method => \&SIGNALduino_OSV1 # Call to process this message
- },
- #"19" => # nothing knowing about this 2015-09-28 01:25:40-MS;P0=-8916;P1=-19904;P2=390;P3=-535;P4=-1020;P5=12846;P6=1371;D=2120232323232324242423232323232323232320239;CP=2;SP=1;
- #
- # {
- # name => 'unknown19',
- # id => '19',
- # one => [1,-2],
- # zero => [1,-1],
- # sync => [1,-50,1,-22],
- # clockabs => 395,
- # format => 'twostate',
- # preamble => 'u19#', # prepend to converted message
- # #clientmodule => '', # not used now
- # #modulematch => '', # not used now
- # length_min => '16',
- # length_max => '32',
- # },
- "20" => #Livolo
- {
- name => 'livolo',
- id => '20',
- one => [3],
- zero => [1],
- start => [5],
- clockabs => 110, #can be 90-140
- format => 'twostate',
- preamble => 'u20#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '16',
- filterfunc => 'SIGNALduino_filterSign',
- },
- "21" => #Einhell Garagentor
- {
- name => 'einhell garagedoor',
- id => '21',
- one => [-3,1],
- zero => [-1,3],
- #sync => [-50,1],
- start => [-50,1],
- clockabs => 400, #ca 400us
- format => 'twostate',
- preamble => 'u21#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '32',
- length_max => '32',
- paddingbits => '1', # This will disable padding
- },
- "22" => #TX-EZ6 / Meteo
- {
- name => 'TX-EZ6',
- id => '22',
- one => [1,-8],
- zero => [1,-3],
- sync => [1,16],
- clockabs => 500, #ca 400us
- format => 'twostate',
- preamble => 'u22#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '40',
- #length_max => '', # must be tested
- },
- "23" => # Pearl Sensor
- {
- name => 'perl unknown',
- id => '23',
- one => [1,-6],
- zero => [1,-1],
- sync => [1,-50],
- clockabs => 200, #ca 200us
- format => 'twostate',
- preamble => 'u23#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '36',
- length_max => '44',
- },
- "24" => # visivon
- {
- name => 'visivon remote',
- id => '24',
- one => [3,-2],
- zero => [1,-5],
- #one => [3,-2],
- #zero => [1,-1],
- start => [30,-5],
- clockabs => 150, #ca 150us
- format => 'twostate',
- preamble => 'u24#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '54',
- length_max => '58',
- },
-
- "25" => # LES remote for led lamp
- {
- name => 'les led remote',
- id => '25',
- one => [-2,1],
- zero => [-1,2],
- sync => [-46,1], # this is a end marker, but we use this as a start marker
- clockabs => 350, #ca 350us
- format => 'twostate',
- preamble => 'u25#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '24',
- length_max => '50', # message has only 24 bit, but we get more than one message, calculation has to be corrected
- },
- "26" => # some remote code send by flamingo style remote controls
- {
- name => 'remote26',
- id => '26',
- one => [1,-3],
- zero => [3,-1],
- # sync => [1,-6], # Message is not provided as MS, due to small fact
- start => [1,-6], # Message is not provided as MS, due to small fact
- clockabs => 380, #ca 380
- format => 'twostate',
- preamble => 'u26#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '24',
- length_max => '24', # message has only 24 bit, but we get more than one message, calculation has to be corrected
- },
- "27" => # some remote code, send by flamingo style remote controls
- {
- name => 'remote27',
- id => '27',
- one => [1,-2],
- zero => [2,-1],
- start => [6,-15], # Message is not provided as MS, worakround is start
- clockabs => 480, #ca 480
- format => 'twostate',
- preamble => 'u27#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '24',
- length_max => '24',
- },
- "28" => # some remote code, send by aldi IC Ledspots
- {
- name => 'IC Ledspot',
- id => '28',
- one => [1,-1],
- zero => [1,-2],
- start => [4,-5],
- clockabs => 600, #ca 600
- format => 'twostate',
- preamble => 'u28#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '8',
- length_max => '8',
- },
- "29" => #
- {
- name => 'HT12e remote',
- id => '29',
- one => [-2,1],
- zero => [-1,2],
- #float => [1,-1],
- start => [-38,1], # Message is not provided as MS, worakround is start
- clockabs => 220, #ca 220
- format => 'tristate', # there is a pause puls between words
- preamble => 'u29#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '10',
- length_max => '12', # message has only 10 bit but is paddet to 12
- },
- "30" => # a unitec remote door reed switch
- {
- name => 'unitec47031',
- id => '30',
- one => [-1,2],
- zero => [-2,1],
- start => [-33,1], # Message is not provided as MS, worakround is start
- clockabs => 300, # ca 300 us
- format => 'twostate', # there is a pause puls between words
- preamble => 'u30#', # prepend to converted message
- clientmodule => 'SD_UT', # not used now
- modulematch => '^u30', # not used now
- length_min => '12',
- length_max => '12', # message has only 10 bit but is paddet to 12
- },
- "31" => # Pollin Isotronic
- {
- name => 'pollin isotronic',
- id => '31',
- one => [-1,2],
- zero => [-2,1],
- start => [1],
- clockabs => 600,
- format => 'twostate',
- preamble => 'u31#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '20',
- length_max => '20',
- },
- "32" => #FreeTec PE-6946 -> http://www.free-tec.de/Funkklingel-mit-Voic-PE-6946-919.shtml
- {
- name => 'freetec 6946',
- id => '32',
- one => [4,-2],
- zero => [1,-5],
- sync => [1,-49],
- clockabs => 140, #ca 140us
- format => 'twostate',
- preamble => 'u32#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '24',
- length_max => '24',
- },
- "33" => #Thermo-/Hygrosensor S014
- {
- name => 'weather33', #
- id => '33',
- one => [1,-8],
- zero => [1,-4],
- sync => [1,-15],
- clockabs => '500', # not used now
- format => 'twostate', # not used now
- preamble => 'W33#', # prepend to converted message
- postamble => '', # Append to converted message
- clientmodule => 'SD_WS', # not used now
- #modulematch => '', # not used now
- length_min => '42',
- length_max => '44',
- },
- "34" =>
- {
- name => 'unknown34',
- id => '34',
- one => [2,-1],
- zero => [1,-2],
- start => [3,-3,3,-3,3,-3,3,-3],
- clockabs => '240',
- format => 'twostate', # not used now
- preamble => 'u34#', # prepend to converted message
- postamble => '', # Append to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '40',
- length_max => '40',
- },
- "35" =>
- {
- name => 'socket35',
- id => '35',
- one => [1,-4],
- zero => [4,-1],
- sync => [1,-19],
- clockabs => '280',
- format => 'twostate', # not used now
- preamble => 'u35#', # prepend to converted message
- postamble => '', # Append to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '28',
- length_max => '32',
- },
- "36" =>
- {
- name => 'socket36',
- id => '36',
- one => [1,-3],
- zero => [1,-1],
- start => [20,-20],
- clockabs => '500',
- format => 'twostate', # not used now
- preamble => 'u36#', # prepend to converted message
- postamble => '', # Append to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '24',
- length_max => '24',
- },
- "37" =>
- {
- name => 'weather37',
- id => '37',
- one => [2,-1],
- zero => [1,-2],
- start => [3,-3,3,-3],
- clockabs => '230',
- format => 'twostate', # not used now
- preamble => 'W37#', # prepend to converted message
- postamble => '', # Append to converted message
- clientmodule => 'SD_WS', # not used now
- #modulematch => '', # not used now
- length_min => '40',
- length_max => '44',
- },
- "38" =>
- {
- name => 'weather38',
- id => '38',
- one => [1,-10],
- zero => [1,-5],
- sync => [1,-25],
- clockabs => '360', # not used now
- format => 'twostate', # not used now
- preamble => 's', # prepend to converted message
- postamble => '00', # Append to converted message
- clientmodule => 'CUL_TCM97001', # not used now
- #modulematch => '^s[A-Fa-f0-9]+', # not used now
- length_min => '32',
- length_max => '32',
- paddingbits => '8',
- },
- "39" => ## X10 Protocol
- {
- name => 'X10 Protocol',
- id => '39',
- one => [1,-3],
- zero => [1,-1],
- start => [16,-4],
- clockabs => 650,
- format => 'twostate',
- preamble => '', # prepend to converted message
- clientmodule => 'RFXX10REC', # not used now
- #modulematch => '^TX......', # not used now
- length_min => '38',
- length_max => '44',
- paddingbits => '8',
- postDemodulation => \&SIGNALduino_lengtnPrefix,
- filterfunc => 'SIGNALduino_compPattern',
-
-
- },
- "40" => ## Romotec
- {
- name => 'romotec',
- id => '40',
- one => [3,-2],
- zero => [1,-3],
- start => [1,-2],
- clockabs => 250,
- preamble => 'u40#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '10',
- },
- "41" => ## Elro (Smartwares) Doorbell DB200
- {
- name => 'elro doorbell',
- comment => 'Elro (Smartwares) Doorbell DB200',
- id => '41',
- zero => [1,-3],
- one => [3,-1],
- sync => [1,-15],
- clockabs => 450,
- preamble => 'u41#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '20',
- },
- "42" => ## MKT Multi Kon Trade
- {
- name => 'MKT motionsensor',
- id => '42',
- zero => [1,-3],
- one => [3,-1],
- start => [-28],
- clockabs => 550,
- preamble => 'u42#', # prepend to converted message
- #clientmodule => '', # not used now
- #modulematch => '',
- length_min => '24',
- },
- "43" => ## Somfy RTS
- {
- name => 'Somfy RTS',
- id => '43',
- clockrange => [610,670], # min , max
- format => 'manchester',
- preamble => 'Ys',
- clientmodule => 'SOMFY', # not used now
- modulematch => '^YsA[0-9A-F]{13}',
- length_min => '56',
- length_max => '56',
- method => \&SIGNALduino_SomfyRTS, # Call to process this message
- msgIntro => 'SR;P0=-2560;P1=2560;P3=-640;D=10101010101010113;',
- #msgOutro => 'SR;P0=-30415;D=0;',
- },
- "44" => ## Bresser Temeo Trend
- {
- name => 'BresserTemeo',
- id => '44',
- clockabs => 500,
- zero => [4,-4],
- one => [4,-8],
- start => [8,-8],
- preamble => 'W44#',
- clientmodule => 'SD_WS',
- modulematch => '^W44#[A-F0-9]{18}',
- length_min => '64',
- length_max => '72',
- },
- "51" => ## Bresser Temeo Trend
- {
- name => 'BresserTemeo',
- id => '44x',
- clockabs => 500,
- zero => [4,-4],
- one => [4,-8],
- start => [8,-12],
- preamble => 'W44x#',
- clientmodule => 'SD_WS',
- modulematch => '^W44x#[A-F0-9]{18}',
- length_min => '64',
- length_max => '72',
- },
- "45" =>
- {
- name => 'revolt',
- id => '45',
- one => [3,-1],
- zero => [1,-3],
- #float => [-1,3], # not full supported now later use
- sync => [1,-24],
- clockabs => -1, # -1=auto
- format => 'twostate', # not used now
- preamble => 'i',
- clientmodule => 'IT', # not used now
- modulematch => '^i......', # not used now
- length_min => '24',
- },
- "46" =>
- {
- name => 'EKX1BE',
- id => '46',
- one => [1,-8],
- zero => [8,-1],
- clockabs => 250, # -1=auto
- format => 'twostate', # not used now
- preamble => 'u46#',
- #clientmodule => '', # not used now
- #modulematch => '', # not used now
- length_min => '16',
- length_max => '18',
-
- },
- "47" => ## maverick
- {
- name => 'Maverick protocol',
- id => '47',
- clockrange => [220,260],
- format => 'manchester',
- preamble => 'P47#', # prepend to converted message
- clientmodule => 'SD_WS_Maverick', # not used now
- modulematch => '^P47#.*', # not used now
- length_min => '100',
- length_max => '108',
- method => \&SIGNALduino_Maverick # Call to process this message
- },
- "48" => ## Joker Dostmann TFA
- {
- name => 'TFA Dostmann',
- id => '48',
- clockabs => 250, # In real it is 500 but this leads to unprceise demodulation
- one => [-4,6],
- zero => [-4,2],
- start => [-6,2],
- format => 'twostate',
- preamble => 'U48#', # prepend to converted message
- #clientmodule => '', # not used now
- modulematch => '^U48#.*', # not used now
- length_min => '47',
- length_max => '48',
- },
- "49" => ## quigg / Aldi gt_9000
- {
- name => 'quigg_gt9000',
- id => '49',
- clockabs => 400,
- one => [2,-1],
- zero => [1,-3],
- start => [-15,2,-1],
- format => 'twostate',
- preamble => 'U49#', # prepend to converted message
- #clientmodule => '', # not used now
- modulematch => '^U49#.*', # not used now
- length_min => '22',
- length_max => '28',
- },
- "50" => ## Opus XT300
- {
- name => 'optus_XT300',
- id => '50',
- clockabs => 500,
- zero => [3,-2],
- one => [1,-2],
- # start => [1,-25], # Wenn das startsignal empfangen wird, fehlt das 1 bit
- format => 'twostate',
- preamble => 'W50#', # prepend to converted message
- clientmodule => 'SD_WS', # not used now
- modulematch => '^W50#.*', # not used now
- length_min => '47',
- length_max => '48',
- },
- );
- sub
- SIGNALduino_Initialize($)
- {
- my ($hash) = @_;
- require "$attr{global}{modpath}/FHEM/DevIo.pm";
- # Provider
- $hash->{ReadFn} = "SIGNALduino_Read";
- $hash->{WriteFn} = "SIGNALduino_Write";
- $hash->{ReadyFn} = "SIGNALduino_Ready";
- # Normal devices
- $hash->{DefFn} = "SIGNALduino_Define";
- $hash->{FingerprintFn} = "SIGNALduino_FingerprintFn";
- $hash->{UndefFn} = "SIGNALduino_Undef";
- $hash->{GetFn} = "SIGNALduino_Get";
- $hash->{SetFn} = "SIGNALduino_Set";
- $hash->{AttrFn} = "SIGNALduino_Attr";
- $hash->{AttrList} =
- "Clients MatchList do_not_notify:1,0 dummy:1,0"
- ." hexFile"
- ." initCommands"
- ." flashCommand"
- ." hardware:nano328,uno,promini328"
- ." debug:0,1"
- ." longids"
- ." minsecs"
- ." whitelist_IDs"
- ." WS09_WSModel:undef,WH1080,CTW600"
- ." WS09_CRCAUS:0,1"
- ." $readingFnAttributes";
- $hash->{ShutdownFn} = "SIGNALduino_Shutdown";
- }
- sub
- SIGNALduino_FingerprintFn($$)
- {
- my ($name, $msg) = @_;
- # Store only the "relevant" part, as the Signalduino won't compute the checksum
- #$msg = substr($msg, 8) if($msg =~ m/^81/ && length($msg) > 8);
- return ($name, $msg);
- }
- #####################################
- sub
- SIGNALduino_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- if(@a != 3) {
- my $msg = "wrong syntax: define <name> SIGNALduino {none | devicename[\@baudrate] | devicename\@directio | hostname:port}";
- Log3 undef, 2, $msg;
- return $msg;
- }
-
- DevIo_CloseDev($hash);
- my $name = $a[0];
-
- if (!exists &round)
- {
- Log3 $name, 1, "$name: Signalduino can't be activated (sub round not found). Please update Fhem via update command";
- return undef;
- }
-
- my $dev = $a[2];
- #Debug "dev: $dev" if ($debug);
- #my $hardware=AttrVal($name,"hardware","nano328");
- #Debug "hardware: $hardware" if ($debug);
-
-
- if($dev eq "none") {
- Log3 $name, 1, "$name: device is none, commands will be echoed only";
- $attr{$name}{dummy} = 1;
- #return undef;
- }
-
- if ($dev ne "none" && $dev =~ m/[a-zA-Z]/ && $dev !~ m/\@/) { # bei einer IP wird kein \@57600 angehaengt
- $dev .= "\@57600";
- }
-
- #$hash->{CMDS} = "";
- $hash->{Clients} = $clientsSIGNALduino;
- $hash->{MatchList} = \%matchListSIGNALduino;
-
- #if( !defined( $attr{$name}{hardware} ) ) {
- # $attr{$name}{hardware} = "nano328";
- #}
- if( !defined( $attr{$name}{flashCommand} ) ) {
- # $attr{$name}{flashCommand} = "avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]"
- $attr{$name}{flashCommand} = "avrdude -c arduino -b 57600 -P [PORT] -p atmega328p -vv -U flash:w:[HEXFILE] 2>[LOGFILE]"
- }
- $hash->{DeviceName} = $dev;
-
- my $ret=undef;
- my $whitelistIDs = AttrVal($name,"whitelist_IDs","");
- SIGNALduino_IdList($hash ,$name, $whitelistIDs);
-
- if($dev ne "none") {
- $ret = DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
- } else {
- $hash->{DevState} = 'initialized';
- readingsSingleUpdate($hash, "state", "opened", 1);
- }
-
- $hash->{DMSG}="nothing";
- $hash->{TIME}=time();
-
-
- Log3 $name, 3, "$name: Firmwareversion: ".$hash->{READINGS}{version}{VAL} if ($hash->{READINGS}{version}{VAL});
- return $ret;
- }
- ###############################
- sub SIGNALduino_Connect($$)
- {
- my ($hash, $err) = @_;
- # damit wird die err-msg nur einmal ausgegeben
- if (!defined($hash->{disConnFlag}) && $err) {
- Log3($hash, 3, "SIGNALduino $hash->{NAME}: ${err}");
- $hash->{disConnFlag} = 1;
- }
- }
- #####################################
- sub
- SIGNALduino_Undef($$)
- {
- my ($hash, $arg) = @_;
- my $name = $hash->{NAME};
- foreach my $d (sort keys %defs) {
- if(defined($defs{$d}) &&
- defined($defs{$d}{IODev}) &&
- $defs{$d}{IODev} == $hash)
- {
- my $lev = ($reread_active ? 4 : 2);
- Log3 $name, $lev, "$name: deleting port for $d";
- delete $defs{$d}{IODev};
- }
- }
- SIGNALduino_Shutdown($hash);
-
- DevIo_CloseDev($hash);
- RemoveInternalTimer($hash);
- return undef;
- }
- #####################################
- sub
- SIGNALduino_Shutdown($)
- {
- my ($hash) = @_;
- #DevIo_SimpleWrite($hash, "XQ\n",2);
- SIGNALduino_SimpleWrite($hash, "XQ"); # Switch reception off, it may hang up the SIGNALduino
- return undef;
- }
- #####################################
- #$hash,$name,"sendmsg","P17;R6#".substr($arg,2)
- sub
- SIGNALduino_Set($@)
- {
- my ($hash, @a) = @_;
-
- return "\"set SIGNALduino\" needs at least one parameter" if(@a < 2);
- if (!defined($sets{$a[1]})) {
- my $arguments = ' ';
- foreach my $arg (sort keys %sets) {
- $arguments.= $arg . ($sets{$arg} ? (':' . $sets{$arg}) : '') . ' ';
- }
- #Log3 $hash, 3, "set arg = $arguments";
- return "Unknown argument $a[1], choose one of " . $arguments;
- }
- my $name = shift @a;
- my $cmd = shift @a;
- my $arg = join(" ", @a);
-
- return "$name is not active, may firmware is not suppoted, please flash or reset" if ($cmd ne 'reset' && $cmd ne 'flash' && exists($hash->{DevState}) && $hash->{DevState} ne 'initialized');
- if($cmd eq "raw") {
- Log3 $name, 4, "set $name $cmd $arg";
- #SIGNALduino_SimpleWrite($hash, $arg);
- SIGNALduino_AddSendQueue($hash,$arg);
- } elsif( $cmd eq "flash" ) {
- my @args = split(' ', $arg);
- my $log = "";
- my $hexFile = "";
- my @deviceName = split('@', $hash->{DeviceName});
- my $port = $deviceName[0];
- my $hardware=AttrVal($name,"hardware","nano328");
- my $defaultHexFile = "./FHEM/firmware/$hash->{TYPE}_$hardware.hex";
- my $logFile = AttrVal("global", "logdir", "./log/") . "$hash->{TYPE}-Flash.log";
- if(!$arg || $args[0] !~ m/^(\w|\/|.)+$/) {
- $hexFile = AttrVal($name, "hexFile", "");
- if ($hexFile eq "") {
- $hexFile = $defaultHexFile;
- }
- }
- else {
- $hexFile = $args[0];
- }
- return "Usage: set $name flash [filename]\n\nor use the hexFile attribute" if($hexFile !~ m/^(\w|\/|.)+$/);
- $log .= "flashing Arduino $name\n";
- $log .= "hex file: $hexFile\n";
- $log .= "port: $port\n";
- $log .= "log file: $logFile\n";
- my $flashCommand = AttrVal($name, "flashCommand", "");
- if($flashCommand ne "") {
- if (-e $logFile) {
- unlink $logFile;
- }
- DevIo_CloseDev($hash);
- $hash->{STATE} = "disconnected";
- $log .= "$name closed\n";
- my $avrdude = $flashCommand;
- $avrdude =~ s/\Q[PORT]\E/$port/g;
- $avrdude =~ s/\Q[HEXFILE]\E/$hexFile/g;
- $avrdude =~ s/\Q[LOGFILE]\E/$logFile/g;
- $log .= "command: $avrdude\n\n";
- `$avrdude`;
- local $/=undef;
- if (-e $logFile) {
- open FILE, $logFile;
- my $logText = <FILE>;
- close FILE;
- $log .= "--- AVRDUDE ---------------------------------------------------------------------------------\n";
- $log .= $logText;
- $log .= "--- AVRDUDE ---------------------------------------------------------------------------------\n\n";
- }
- else {
- $log .= "WARNING: avrdude created no log file\n\n";
- }
- }
- else {
- $log .= "\n\nNo flashCommand found. Please define this attribute.\n\n";
- }
- DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
- $log .= "$name opened\n";
- return $log;
- } elsif ($cmd =~ m/reset/i) {
- delete($hash->{initResetFlag}) if defined($hash->{initResetFlag});
- return SIGNALduino_ResetDevice($hash);
- } elsif( $cmd eq "close" ) {
- $hash->{DevState} = 'closed';
- return SIGNALduino_CloseDevice($hash);
- } elsif( $cmd eq "ITClock" ) {
- Log3 $name, 4, "set $name $cmd $arg";
- my $clock = shift @a;
-
- $clock=250 if ($clock eq "" );
- return "argument $arg is not numeric" if($clock !~ /^\d+$/);
- Log3 $name, 3, "$name: Setting ITClock to $clock (sending $arg)";
- $arg="ic$clock";
- #SIGNALduino_SimpleWrite($hash, $arg);
- SIGNALduino_AddSendQueue($hash,$arg);
- $hash->{$cmd}=$clock;
- } elsif( $cmd eq "disableMessagetype" ) {
- my $argm = 'CD' . substr($arg,-1,1);
- #SIGNALduino_SimpleWrite($hash, $argm);
- SIGNALduino_AddSendQueue($hash,$argm);
- Log3 $name, 4, "set $name $cmd $arg $argm";;
- } elsif( $cmd eq "enableMessagetype" ) {
- my $argm = 'CE' . substr($arg,-1,1);
- #SIGNALduino_SimpleWrite($hash, $argm);
- SIGNALduino_AddSendQueue($hash,$argm);
- Log3 $name, 4, "set $name $cmd $arg $argm";
- } elsif( $cmd eq "sendMsg" ) {
- my ($protocol,$data,$repeats,$clock) = split("#",$arg);
- $protocol=~ s/[Pp](\d+)/$1/; # extract protocol num
- $repeats=~ s/[rR](\d+)/$1/; # extract repeat num
- $clock=~ s/[Cc](\d+)/$1/ if (defined($clock)); # extract ITClock num
- $repeats=1 if (!defined($repeats));
-
- return "$name: sendmsg, unknown protocol: $protocol" if (!exists($ProtocolListSIGNALduino{$protocol}));
-
- #print ("data = $data \n");
- #print ("protocol = $protocol \n");
- #print ("repeats = $repeats \n");
-
- my %signalHash;
- my %patternHash;
- my $pattern="";
- my $cnt=0;
-
-
- my $sendData;
- if ($ProtocolListSIGNALduino{$protocol}{format} eq 'manchester')
- {
- #$clock = (map { $clock += $_ } @{$ProtocolListSIGNALduino{$protocol}{clockrange}}) / 2 if (!defined($clock));
-
- $clock += $_ for(@{$ProtocolListSIGNALduino{$protocol}{clockrange}});
- $clock = round($clock/2,0);
- if ($protocol == 43) {
- #$data =~ tr/0123456789ABCDEF/FEDCBA9876543210/;
- }
-
- my $intro = "";
- my $outro = "";
-
- $intro = $ProtocolListSIGNALduino{$protocol}{msgIntro} if ($ProtocolListSIGNALduino{$protocol}{msgIntro});
- $outro = $ProtocolListSIGNALduino{$protocol}{msgOutro}.";" if ($ProtocolListSIGNALduino{$protocol}{msgOutro});
- if ($intro ne "" || $outro ne "")
- {
- $intro = "SC;R=$repeats;" . $intro;
- $repeats = 0;
- }
- $sendData = $intro . "SM;" . ($repeats > 0 ? "R=$repeats;" : "") . "C=$clock;D=$data;" . $outro; # SM;R=2;C=400;D=AFAFAF;
- Log3 $name, 5, "$name: sendmsg Preparing manchester protocol=$protocol, repeats=$repeats, clock=$clock data=$data";
- } else {
- if ($protocol == 3 || substr($data,0,2) eq "is") {
- if (substr($data,0,2) eq "is") {
- $data = substr($data,2); # is am Anfang entfernen
- }
- $data = SIGNALduino_ITV1_tristateToBit($data);
- Log3 $name, 5, "$name: sendmsg IT V1 convertet tristate to bits=$data";
- }
- if (!defined($clock)) {
- $hash->{ITClock} = 250 if (!defined($hash->{ITClock})); # Todo: Klaeren wo ITClock verwendet wird und ob wir diesen Teil nicht auf Protokoll 3,4 und 17 minimieren
- $clock=$ProtocolListSIGNALduino{$protocol}{clockabs} > 1 ?$ProtocolListSIGNALduino{$protocol}{clockabs}:$hash->{ITClock};
- }
- Log3 $name, 5, "$name: sendmsg Preparing rawsend command for protocol=$protocol, repeats=$repeats, clock=$clock bits=$data";
-
- foreach my $item (qw(sync start one zero float))
- {
- #print ("item= $item \n");
- next if (!exists($ProtocolListSIGNALduino{$protocol}{$item}));
-
- foreach my $p (@{$ProtocolListSIGNALduino{$protocol}{$item}})
- {
- #print (" p = $p \n");
-
- if (!exists($patternHash{$p}))
- {
- $patternHash{$p}=$cnt;
- $pattern.="P".$patternHash{$p}."=".$p*$clock.";";
- $cnt++;
- }
- $signalHash{$item}.=$patternHash{$p};
- #print (" signalHash{$item} = $signalHash{$item} \n");
- }
- }
- my @bits = split("", $data);
-
- my %bitconv = (1=>"one", 0=>"zero", 'D'=> "float");
- my $SignalData="D=";
-
- $SignalData.=$signalHash{sync} if (exists($signalHash{sync}));
- $SignalData.=$signalHash{start} if (exists($signalHash{start}));
- foreach my $bit (@bits)
- {
- next if (!exists($bitconv{$bit}));
- #Log3 $name, 5, "encoding $bit";
- $SignalData.=$signalHash{$bitconv{$bit}}; ## Add the signal to our data string
- }
- $sendData = "SR;R=$repeats;$pattern$SignalData;";
- }
-
- #SIGNALduino_SimpleWrite($hash, $sendData);
- SIGNALduino_AddSendQueue($hash,$sendData);
- Log3 $name, 4, "$name/set: sending via SendMsg: $sendData";
-
- } else {
- Log3 $name, 5, "$name/set: set $name $cmd $arg";
- #SIGNALduino_SimpleWrite($hash, $arg);
- return "Unknown argument $cmd, choose one of ". ReadingsVal($name,'cmd',' help me');
- }
- return undef;
- }
- #####################################
- sub
- SIGNALduino_Get($@)
- {
- my ($hash, @a) = @_;
- my $type = $hash->{TYPE};
- my $name = $hash->{NAME};
- return "$name is not active, may firmware is not suppoted, please flash or reset" if (exists($hash->{DevState}) && $hash->{DevState} ne 'initialized');
- #my $name = $a[0];
-
- Log3 $name, 5, "\"get $type\" needs at least one parameter" if(@a < 2);
- return "\"get $type\" needs at least one parameter" if(@a < 2);
- if(!defined($gets{$a[1]})) {
- my @cList = map { $_ =~ m/^(file|raw)$/ ? $_ : "$_:noArg" } sort keys %gets;
- return "Unknown argument $a[1], choose one of " . join(" ", @cList);
- }
- my $arg = ($a[2] ? $a[2] : "");
- return "no command to send, get aborted." if (length($gets{$a[1]}[0]) == 0 && length($arg) == 0);
-
- my ($msg, $err);
- if (IsDummy($name))
- {
- if ($arg =~ /^M[CSU];.*/)
- {
- $arg="\002$arg\003"; ## Add start end end marker if not already there
- Log3 $name, 5, "$name/msg adding start and endmarker to message";
-
- }
- if ($arg =~ /\002M.;.*;\003$/)
- {
- Log3 $name, 4, "$name/msg get raw: $arg";
- return SIGNALduino_Parse($hash, $hash, $hash->{NAME}, $arg);
- }
- else {
- my $arg2 = "";
- if ($arg =~ m/^version=/) { # set version
- $arg2 = substr($arg,8);
- $hash->{version} = "V " . $arg2;
- }
- elsif ($arg =~ m/^regexp=/) { # set fileRegexp for get raw messages from file
- $arg2 = substr($arg,7);
- $hash->{fileRegexp} = $arg2;
- delete($hash->{fileRegexp}) if (!$arg2);
- }
- elsif ($arg =~ m/^file=/) {
- $arg2 = substr($arg,5);
- my $n = 0;
- if (open(my $fh, '<', $arg2)) {
- my $fileRegexp = $hash->{fileRegexp};
- while (my $row = <$fh>) {
- if ($row =~ /.*\002M.;.*;\003$/) {
- chomp $row;
- $row =~ s/.*\002(M.;.*;)\003/$1/;
- if (!defined($fileRegexp) || $row =~ m/$fileRegexp/) {
- $n += 1;
- $row="\002$row\003";
- Log3 $name, 4, "$name/msg fileGetRaw: $row";
- SIGNALduino_Parse($hash, $hash, $hash->{NAME}, $row);
- }
- }
- }
- return $n . " raw Nachrichten eingelesen";
- } else {
- return "Could not open file $arg2";
- }
- }
- elsif ($arg eq '?') {
- my $ret;
-
- $ret = "dummy get raw\n\n";
- $ret .= "raw message e.g. MS;P0=-392;P1=...\n";
- $ret .= "dispatch message e.g. P7#6290DCF37\n";
- $ret .= "version=x.x.x sets version. e.g. (version=3.2.0) to get old MC messages\n";
- $ret .= "regexp= set fileRegexp for get raw messages from file. e.g. regexp=^MC\n";
- $ret .= "file= gets raw messages from file in the fhem directory\n";
- return $ret;
- }
- else {
- Log3 $name, 4, "$name/msg get dispatch: $arg";
- Dispatch($hash, $arg, undef);
- }
- return "";
- }
- }
- return "No $a[1] for dummies" if(IsDummy($name));
- Log3 $name, 5, "$name: command for gets: " . $gets{$a[1]}[0] . " " . $arg;
- if ($a[1] eq "raw")
- {
- # Dirty hack to check and modify direct communication from logical modules with hardware
- if ($arg =~ /^is.*/ && length($arg) == 34)
- {
- # Arctec protocol
- Log3 $name, 5, "$name: calling set :sendmsg P17;R6#".substr($arg,2);
-
- SIGNALduino_Set($hash,$name,"sendMsg","P17#",substr($arg,2),"#R6");
- return "$a[0] $a[1] => $arg";
- }
-
- }
- elsif ($a[1] eq "protocolIDs")
- {
- my $id;
- my $ret;
- my $s;
- my $moduleId;
- my @IdList = ();
-
- foreach $id (keys %ProtocolListSIGNALduino)
- {
- next if ($id eq 'id');
- push (@IdList, $id);
- }
- @IdList = sort { $a <=> $b } @IdList;
-
- $ret = " ID modulname protocolname # comment\n\n";
-
- foreach $id (@IdList)
- {
- $ret .= sprintf("%3s",$id) . " ";
-
- if (exists ($ProtocolListSIGNALduino{$id}{format}) && $ProtocolListSIGNALduino{$id}{format} eq "manchester")
- {
- $ret .= "MC";
- }
- elsif (exists $ProtocolListSIGNALduino{$id}{sync})
- {
- $ret .= "MS";
- }
- elsif (exists ($ProtocolListSIGNALduino{$id}{clockabs}))
- {
- $ret .= "MU";
- }
-
- if (exists ($ProtocolListSIGNALduino{$id}{clientmodule}))
- {
- $moduleId .= "$id,";
- $s = $ProtocolListSIGNALduino{$id}{clientmodule};
- if (length($s) < 15)
- {
- $s .= substr(" ",length($s) - 15);
- }
- $ret .= " $s";
- }
- else
- {
- $ret .= " ";
- }
-
- if (exists ($ProtocolListSIGNALduino{$id}{name}))
- {
- $ret .= " $ProtocolListSIGNALduino{$id}{name}";
- }
-
- if (exists ($ProtocolListSIGNALduino{$id}{comment}))
- {
- $ret .= " # $ProtocolListSIGNALduino{$id}{comment}";
- }
-
- $ret .= "\n";
- }
- $moduleId =~ s/,$//;
-
- return "$a[1]: \n\n$ret\nIds with modules: $moduleId";
- }
-
- #SIGNALduino_SimpleWrite($hash, $gets{$a[1]}[0] . $arg);
- SIGNALduino_AddSendQueue($hash, $gets{$a[1]}[0] . $arg);
- $hash->{getcmd}->{cmd}=$a[1];
- $hash->{getcmd}->{asyncOut}=$hash->{CL};
- $hash->{getcmd}->{timenow}=time();
-
- return undef; # We will exit here, and give an output only, if asny output is supported. If this is not supported, only the readings are updated
- }
- sub SIGNALduino_parseResponse($$$)
- {
- my $hash = shift;
- my $cmd = shift;
- my $msg = shift;
- my $name=$hash->{NAME};
-
- $msg =~ s/[\r\n]//g;
- if($cmd eq "cmds")
- { # nice it up
- $msg =~ s/$name cmds =>//g;
- $msg =~ s/.*Use one of//g;
- }
- elsif($cmd eq "uptime")
- { # decode it
- #$msg = hex($msg); # /125; only for col or coc
- $msg = sprintf("%d %02d:%02d:%02d", $msg/86400, ($msg%86400)/3600, ($msg%3600)/60, $msg%60);
- }
-
- return $msg;
- }
- #####################################
- sub
- SIGNALduino_ResetDevice($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- Log3 $hash, 3, "$name reset";
- DevIo_CloseDev($hash);
- my $ret = DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
- return $ret;
- }
- #####################################
- sub
- SIGNALduino_CloseDevice($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- Log3 $hash, 2, "$name closed";
- RemoveInternalTimer($hash);
- DevIo_CloseDev($hash);
- readingsSingleUpdate($hash, "state", "closed", 1);
-
- return undef;
- }
- #####################################
- sub
- SIGNALduino_DoInit($)
- {
- my $hash = shift;
- my $name = $hash->{NAME};
- my $err;
- my $msg = undef;
- my ($ver, $try) = ("", 0);
- #Dirty hack to allow initialisation of DirectIO Device for some debugging and tesing
- Log3 $hash, 1, "$name/define: ".$hash->{DEF};
-
- delete($hash->{disConnFlag}) if defined($hash->{disConnFlag});
-
- RemoveInternalTimer("HandleWriteQueue:$name");
- @{$hash->{QUEUE}} = ();
- if (($hash->{DEF} !~ m/\@DirectIO/) and ($hash->{DEF} !~ m/none/) )
- {
- Log3 $hash, 1, "$name/init: ".$hash->{DEF};
- $hash->{initretry} = 0;
- RemoveInternalTimer($hash);
-
- #SIGNALduino_SimpleWrite($hash, "XQ"); # Disable receiver
- InternalTimer(gettimeofday() + SDUINO_INIT_WAIT_XQ, "SIGNALduino_SimpleWrite_XQ", $hash, 0);
-
- InternalTimer(gettimeofday() + SDUINO_INIT_WAIT, "SIGNALduino_StartInit", $hash, 0);
- }
- # Reset the counter
- delete($hash->{XMIT_TIME});
- delete($hash->{NR_CMD_LAST_H});
- return;
- #return undef;
- }
- # Disable receiver
- sub SIGNALduino_SimpleWrite_XQ($) {
- my ($hash) = @_;
- my $name = $hash->{NAME};
-
- Log3 $hash, 3, "$name/init: disable receiver (XQ)";
- SIGNALduino_SimpleWrite($hash, "XQ");
- #DevIo_SimpleWrite($hash, "XQ\n",2);
- }
- sub SIGNALduino_StartInit($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- $hash->{version} = undef;
-
- Log3 $name,3 , "$name/init: get version, retry = " . $hash->{initretry};
- if ($hash->{initretry} >= SDUINO_INIT_MAXRETRY) {
- $hash->{DevState} = 'INACTIVE';
- # einmaliger reset, wenn danach immer noch 'init retry count reached', dann SIGNALduino_CloseDevice()
- if (!defined($hash->{initResetFlag})) {
- Log3 $name,2 , "$name/init retry count reached. Reset";
- $hash->{initResetFlag} = 1;
- SIGNALduino_ResetDevice($hash);
- } else {
- Log3 $name,2 , "$name/init retry count reached. Closed";
- SIGNALduino_CloseDevice($hash);
- }
- return;
- }
- else {
- $hash->{getcmd}->{cmd} = "version";
- SIGNALduino_SimpleWrite($hash, "V");
- #DevIo_SimpleWrite($hash, "V\n",2);
- $hash->{DevState} = 'waitInit';
- RemoveInternalTimer($hash);
- InternalTimer(gettimeofday() + SDUINO_CMD_TIMEOUT, "SIGNALduino_CheckCmdResp", $hash, 0);
- }
- }
- ####################
- sub SIGNALduino_CheckCmdResp($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- my $msg = undef;
- my $ver;
-
- if ($hash->{version}) {
- $ver = $hash->{version};
- if ($ver !~ m/SIGNAL(duino|ESP)/) {
- $msg = "$name: Not an SIGNALduino device, setting attribute dummy=1 got for V: $ver";
- Log3 $hash, 1, $msg;
- readingsSingleUpdate($hash, "state", "no SIGNALduino found", 1);
- $hash->{DevState} = 'INACTIVE';
- SIGNALduino_CloseDevice($hash);
- }
- elsif($ver =~ m/^V 3\.1\./) {
- $msg = "$name: Version of your arduino is not compatible, pleas flash new firmware. (device closed) Got for V: $ver";
- readingsSingleUpdate($hash, "state", "unsupported firmware found", 1);
- Log3 $hash, 1, $msg;
- $hash->{DevState} = 'INACTIVE';
- SIGNALduino_CloseDevice($hash);
- }
- else {
- readingsSingleUpdate($hash, "state", "opened", 1);
- Log3 $name, 2, "$name: initialized. " . SDUINO_VERSION;
- $hash->{DevState} = 'initialized';
- delete($hash->{initResetFlag}) if defined($hash->{initResetFlag});
- SIGNALduino_SimpleWrite($hash, "XE"); # Enable receiver
- #DevIo_SimpleWrite($hash, "XE\n",2);
- Log3 $hash, 3, "$name/init: enable receiver (XE)";
- delete($hash->{initretry});
- # initialize keepalive
- $hash->{keepalive}{ok} = 0;
- $hash->{keepalive}{retry} = 0;
- InternalTimer(gettimeofday() + SDUINO_KEEPALIVE_TIMEOUT, "SIGNALduino_KeepAlive", $hash, 0);
- }
- }
- else {
- delete($hash->{getcmd});
- $hash->{initretry} ++;
- #InternalTimer(gettimeofday()+1, "SIGNALduino_StartInit", $hash, 0);
- SIGNALduino_StartInit($hash);
- }
- }
- #####################################
- # Check if the 1% limit is reached and trigger notifies
- sub
- SIGNALduino_XmitLimitCheck($$)
- {
- my ($hash,$fn) = @_;
-
-
- return if ($fn !~ m/^(is|SR).*/);
- my $now = time();
- if(!$hash->{XMIT_TIME}) {
- $hash->{XMIT_TIME}[0] = $now;
- $hash->{NR_CMD_LAST_H} = 1;
- return;
- }
- my $nowM1h = $now-3600;
- my @b = grep { $_ > $nowM1h } @{$hash->{XMIT_TIME}};
- if(@b > 163) { # Maximum nr of transmissions per hour (unconfirmed).
- my $name = $hash->{NAME};
- Log3 $name, 2, "SIGNALduino TRANSMIT LIMIT EXCEEDED";
- DoTrigger($name, "TRANSMIT LIMIT EXCEEDED");
- } else {
- push(@b, $now);
- }
- $hash->{XMIT_TIME} = \@b;
- $hash->{NR_CMD_LAST_H} = int(@b);
- }
- #####################################
- ## API to logical modules: Provide as Hash of IO Device, type of function ; command to call ; message to send
- sub
- SIGNALduino_Write($$$)
- {
- my ($hash,$fn,$msg) = @_;
- my $name = $hash->{NAME};
- $fn="RAW" if $fn eq "";
- Log3 $name, 5, "$name/write: adding to queue $fn $msg";
- #SIGNALduino_SimpleWrite($hash, $bstring);
-
- SIGNALduino_Set($hash,$name,$fn,$msg);
- #SIGNALduino_AddSendQueue($hash,$bstring);
-
- }
- sub SIGNALduino_AddSendQueue($$)
- {
- my ($hash, $msg) = @_;
- my $name = $hash->{NAME};
-
- #Log3 $hash, 3,"AddSendQueue: " . $hash->{NAME} . ": $msg";
-
- push(@{$hash->{QUEUE}}, $msg);
-
- #Log3 $hash , 5, Dumper($hash->{QUEUE});
-
- InternalTimer(gettimeofday() + 0.1, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name") if (@{$hash->{QUEUE}} == 1);
- }
- sub
- SIGNALduino_SendFromQueue($$)
- {
- my ($hash, $msg) = @_;
- my $name = $hash->{NAME};
-
- if($msg ne "") {
- SIGNALduino_XmitLimitCheck($hash,$msg);
- #DevIo_SimpleWrite($hash, $msg . "\n", 2);
- SIGNALduino_SimpleWrite($hash,$msg);
- if ($msg =~ m/^S(R|C|M);/) {
- $hash->{getcmd}->{cmd} = 'sendraw';
- Log3 $hash, 4, "$name SendFromQueue: msg=$msg"; # zu testen der Queue, kann wenn es funktioniert auskommentiert werden
- }
- }
- ##############
- # Write the next buffer not earlier than 0.23 seconds
- # else it will be sent too early by the SIGNALduino, resulting in a collision, or may the last command is not finished
-
- if (defined($hash->{getcmd}->{cmd}) && $hash->{getcmd}->{cmd} eq 'sendraw') {
- InternalTimer(gettimeofday() + SDUINO_WRITEQUEUE_TIMEOUT, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name");
- } else {
- InternalTimer(gettimeofday() + SDUINO_WRITEQUEUE_NEXT, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name");
- }
- }
- ####################################
- sub
- SIGNALduino_HandleWriteQueue($)
- {
- my($param) = @_;
- my(undef,$name) = split(':', $param);
- my $hash = $defs{$name};
-
- #my @arr = @{$hash->{QUEUE}};
-
- if (defined($hash->{getcmd}->{cmd}) && $hash->{getcmd}->{cmd} eq 'sendraw') {
- Log3 $name, 4, "$name/HandleWriteQueue: sendraw no answer (timeout)";
- delete($hash->{getcmd});
- }
-
- if(@{$hash->{QUEUE}}) {
- my $msg= shift(@{$hash->{QUEUE}});
- if($msg eq "") {
- SIGNALduino_HandleWriteQueue("x:$name");
- } else {
- SIGNALduino_SendFromQueue($hash, $msg);
- }
- } else {
- Log3 $name, 4, "$name/HandleWriteQueue: nothing to send, stopping timer";
- RemoveInternalTimer("HandleWriteQueue:$name");
- }
- }
- #####################################
- # called from the global loop, when the select for hash->{FD} reports data
- sub
- SIGNALduino_Read($)
- {
- my ($hash) = @_;
- my $buf = DevIo_SimpleRead($hash);
- return "" if(!defined($buf));
- my $name = $hash->{NAME};
- my $debug = AttrVal($name,"debug",0);
- my $SIGNALduinodata = $hash->{PARTIAL};
- Log3 $name, 5, "$name/RAW READ: $SIGNALduinodata/$buf" if ($debug);
- $SIGNALduinodata .= $buf;
- while($SIGNALduinodata =~ m/\n/) {
- my $rmsg;
- ($rmsg,$SIGNALduinodata) = split("\n", $SIGNALduinodata, 2);
- $rmsg =~ s/\r//;
- Log3 $name, 4, "$name/msg READ: $rmsg";
- if ( $rmsg && !SIGNALduino_Parse($hash, $hash, $name, $rmsg) && defined($hash->{getcmd}) && defined($hash->{getcmd}->{cmd}))
- {
- my $regexp;
- if ($hash->{getcmd}->{cmd} eq 'sendraw') {
- $regexp = '^S(R|C|M);';
- }
- else {
- $regexp = $gets{$hash->{getcmd}->{cmd}}[1];
- }
- if(!defined($regexp) || $rmsg =~ m/$regexp/) {
- if (defined($hash->{keepalive})) {
- $hash->{keepalive}{ok} = 1;
- $hash->{keepalive}{retry} = 0;
- }
- Log3 $name, 5, "$name/msg READ: regexp=$regexp cmd=$hash->{getcmd}->{cmd} msg=$rmsg";
-
- if ($hash->{getcmd}->{cmd} eq 'version') {
- my $msg_start = index($rmsg, 'V 3.');
- if ($msg_start > 0) {
- $rmsg = substr($rmsg, $msg_start);
- Log3 $name, 4, "$name/read: cut chars at begin. msgstart = $msg_start msg = $rmsg";
- }
- $hash->{version} = $rmsg;
- if (defined($hash->{DevState}) && $hash->{DevState} eq 'waitInit') {
- RemoveInternalTimer($hash);
- SIGNALduino_CheckCmdResp($hash);
- }
- }
- if ($hash->{getcmd}->{cmd} eq 'sendraw') {
- # zu testen der sendeQueue, kann wenn es funktioniert auf verbose 5
- Log3 $name, 4, "$name/read sendraw answer: $rmsg";
- delete($hash->{getcmd});
- RemoveInternalTimer("HandleWriteQueue:$name");
- SIGNALduino_HandleWriteQueue("x:$name");
- }
- else {
- $rmsg = SIGNALduino_parseResponse($hash,$hash->{getcmd}->{cmd},$rmsg);
- readingsSingleUpdate($hash, $hash->{getcmd}->{cmd}, $rmsg, 0);
- if (defined($hash->{getcmd}->{asyncOut})) {
- #Log3 $name, 4, "$name/msg READ: asyncOutput";
- my $ao = asyncOutput( $hash->{getcmd}->{asyncOut}, $hash->{getcmd}->{cmd}.": " . $rmsg );
- }
- delete($hash->{getcmd});
- }
- } else {
- Log3 $name, 4, "$name/msg READ: Received answer ($rmsg) for ". $hash->{getcmd}->{cmd}." does not match $regexp";
- }
- }
- }
- $hash->{PARTIAL} = $SIGNALduinodata;
- }
- sub SIGNALduino_KeepAlive($){
- my ($hash) = @_;
- my $name = $hash->{NAME};
-
- return if ($hash->{DevState} eq 'disconnected');
-
- Log3 $name,4 , "$name/KeepAliveOk: " . $hash->{keepalive}{ok};
- if (!$hash->{keepalive}{ok}) {
- delete($hash->{getcmd});
- if ($hash->{keepalive}{retry} >= SDUINO_KEEPALIVE_MAXRETRY) {
- Log3 $name,4 , "$name/keepalive retry count reached. Reset";
- $hash->{DevState} = 'INACTIVE';
- SIGNALduino_ResetDevice($hash);
- return;
- }
- else {
- $hash->{keepalive}{retry} ++;
- Log3 $name,3 , "$name/KeepAliveOk: " . $hash->{keepalive}{ok} . " retry = " . $hash->{keepalive}{retry} . " -> get ping";
- $hash->{getcmd}->{cmd} = "ping";
- SIGNALduino_AddSendQueue($hash, "P");
- #SIGNALduino_SimpleWrite($hash, "P");
- }
- }
- Log3 $name,4 , "$name/keepalive retry = " . $hash->{keepalive}{retry};
- $hash->{keepalive}{ok} = 0;
-
- InternalTimer(gettimeofday() + SDUINO_KEEPALIVE_TIMEOUT, "SIGNALduino_KeepAlive", $hash);
- }
- ### Helper Subs >>>
- sub SIGNALduino_splitMsg
- {
- my $txt = shift;
- my $delim = shift;
- my @msg_parts = split(/$delim/,$txt);
-
- return @msg_parts;
- }
- # $value - $set <= $tolerance
- sub SIGNALduino_inTol($$$)
- {
- #Debug "sduino abs \($_[0] - $_[1]\) <= $_[2] ";
- return (abs($_[0]-$_[1])<=$_[2]);
- }
- # - - - - - - - - - - - -
- #=item SIGNALduino_PatternExists()
- #This functons, needs reference to $hash, @array of values to search and %patternList where to find the matches.
- #
- # Will return -1 if pattern is not found or a string, containing the indexes which are in tolerance and have the smallest gap to what we searched
- # =cut
- # 01232323242423 while ($message =~ /$pstr/g) { $count++ }
- sub SIGNALduino_PatternExists
- {
- my ($hash,$search,$patternList,$data) = @_;
- #my %patternList=$arg3;
- #Debug "plist: ".Dumper($patternList) if($debug);
- #Debug "searchlist: ".Dumper($search) if($debug);
- my $searchpattern;
- my $valid=1;
- my @pstr;
- my $debug = AttrVal($hash->{NAME},"debug",0);
-
- my $i=0;
-
- my $maxcol=0;
-
- foreach $searchpattern (@{$search}) # z.B. [1, -4]
- {
- #my $patt_id;
- # Calculate tolernace for search
- #my $tol=abs(abs($searchpattern)>=2 ?$searchpattern*0.3:$searchpattern*1.5);
- my $tol=abs(abs($searchpattern)>3 ? abs($searchpattern)>16 ? $searchpattern*0.18 : $searchpattern*0.3 : 1); #tol is minimum 1 or higer, depending on our searched pulselengh
-
- Debug "tol: looking for ($searchpattern +- $tol)" if($debug);
-
- my %pattern_gap ; #= {};
- # Find and store the gap of every pattern, which is in tolerance
- %pattern_gap = map { $_ => abs($patternList->{$_}-$searchpattern) } grep { abs($patternList->{$_}-$searchpattern) <= $tol} (keys %$patternList);
- if (scalar keys %pattern_gap > 0)
- {
- Debug "index => gap in tol (+- $tol) of pulse ($searchpattern) : ".Dumper(\%pattern_gap) if($debug);
- # Extract fist pattern, which is nearst to our searched value
- my @closestidx = (sort {$pattern_gap{$a} <=> $pattern_gap{$b}} keys %pattern_gap);
-
- my $idxstr="";
- my $r=0;
-
- while (my ($item) = splice(@closestidx, 0, 1))
- {
- $pstr[$i][$r]=$item;
- $r++;
- Debug "closest pattern has index: $item" if($debug);
- }
- $valid=1;
- } else {
- # search is not found, return -1
- return -1;
- last;
- }
- $i++;
- #return ($valid ? $pstr : -1); # return $pstr if $valid or -1
-
- #foreach $patt_id (keys %$patternList) {
- #Debug "$patt_id. chk ->intol $patternList->{$patt_id} $searchpattern $tol";
- #$valid = SIGNALduino_inTol($patternList->{$patt_id}, $searchpattern, $tol);
- #if ( $valid) #one pulse found in tolerance, search next one
- #{
- # $pstr="$pstr$patt_id";
- # # provide this index for further lookup table -> {$patt_id = $searchpattern}
- # Debug "pulse found";
- # last ; ## Exit foreach loop if searched pattern matches pattern in list
- #}
- #}
- #last if (!$valid); ## Exit loop if a complete iteration has not found anything
- }
- my @results = ('');
-
- foreach my $subarray (@pstr)
- {
- @results = map {my $res = $_; map $res.$_, @$subarray } @results;
- }
-
- foreach my $search (@results)
- {
- Debug "looking for substr $search" if($debug);
-
- return $search if (index( ${$data}, $search) >= 0);
- }
-
- return -1;
-
- #return ($valid ? @results : -1); # return @pstr if $valid or -1
- }
- #SIGNALduino_MatchSignalPattern{$hash,@array, %hash, @array, $scalar}; not used >v3.1.3
- sub SIGNALduino_MatchSignalPattern($\@\%\@$){
- my ( $hash, $signalpattern, $patternList, $data_array, $idx) = @_;
- my $name = $hash->{NAME};
- #print Dumper($patternList);
- #print Dumper($idx);
- #Debug Dumper($signalpattern) if ($debug);
- my $tol="0.2"; # Tolerance factor
- my $found=0;
- my $debug = AttrVal($hash->{NAME},"debug",0);
-
- foreach ( @{$signalpattern} )
- {
- #Debug " $idx check: ".$patternList->{$data_array->[$idx]}." == ".$_;
- Debug "$name: idx: $idx check: abs(". $patternList->{$data_array->[$idx]}." - ".$_.") > ". ceil(abs($patternList->{$data_array->[$idx]}*$tol)) if ($debug);
-
- #print "\n";;
- #if ($patternList->{$data_array->[$idx]} ne $_ )
- ### Nachkommastelle von ceil!!!
- if (!defined( $patternList->{$data_array->[$idx]})){
- Debug "$name: Error index ($idx) does not exist!!" if ($debug);
- return -1;
- }
- if (abs($patternList->{$data_array->[$idx]} - $_) > ceil(abs($patternList->{$data_array->[$idx]}*$tol)))
- {
- return -1; ## Pattern does not match, return -1 = not matched
- }
- $found=1;
- $idx++;
- }
- if ($found)
- {
- return $idx; ## Return new Index Position
- }
-
- }
- sub SIGNALduino_b2h {
- my $num = shift;
- my $WIDTH = 4;
- my $index = length($num) - $WIDTH;
- my $hex = '';
- do {
- my $width = $WIDTH;
- if ($index < 0) {
- $width += $index;
- $index = 0;
- }
- my $cut_string = substr($num, $index, $width);
- $hex = sprintf('%X', oct("0b$cut_string")) . $hex;
- $index -= $WIDTH;
- } while ($index > (-1 * $WIDTH));
- return $hex;
- }
- sub SIGNALduino_Split_Message($$)
- {
- my $rmsg = shift;
- my $name = shift;
- my %patternList;
- my $clockidx;
- my $syncidx;
- my $rawData;
- my $clockabs;
- my $mcbitnum;
-
- my @msg_parts = SIGNALduino_splitMsg($rmsg,';'); ## Split message parts by ";"
- my %ret;
- my $debug = AttrVal($name,"debug",0);
-
- foreach (@msg_parts)
- {
- #Debug "$name: checking msg part:( $_ )" if ($debug);
- if ($_ =~ m/^MS/ or $_ =~ m/^MC/ or $_ =~ m/^MU/) #### Synced Message start
- {
- $ret{messagetype} = $_;
- }
- elsif ($_ =~ m/^P\d=-?\d{2,}/ or $_ =~ m/^[SL][LH]=-?\d{2,}/) #### Extract Pattern List from array
- {
- $_ =~ s/^P+//;
- $_ =~ s/^P\d//;
- my @pattern = split(/=/,$_);
-
- $patternList{$pattern[0]} = $pattern[1];
- Debug "$name: extracted pattern @pattern \n" if ($debug);
- }
- elsif($_ =~ m/D=\d+/ or $_ =~ m/^D=[A-F0-9]+/) #### Message from array
- {
- $_ =~ s/D=//;
- $rawData = $_ ;
- Debug "$name: extracted data $rawData\n" if ($debug);
- $ret{rawData} = $rawData;
- }
- elsif($_ =~ m/^SP=\d{1}/) #### Sync Pulse Index
- {
- (undef, $syncidx) = split(/=/,$_);
- Debug "$name: extracted syncidx $syncidx\n" if ($debug);
- #return undef if (!defined($patternList{$syncidx}));
- $ret{syncidx} = $syncidx;
- }
- elsif($_ =~ m/^CP=\d{1}/) #### Clock Pulse Index
- {
- (undef, $clockidx) = split(/=/,$_);
- Debug "$name: extracted clockidx $clockidx\n" if ($debug);;
- #return undef if (!defined($patternList{$clockidx}));
- $ret{clockidx} = $clockidx;
- }
- elsif($_ =~ m/^L=\d/) #### MC bit length
- {
- (undef, $mcbitnum) = split(/=/,$_);
- Debug "$name: extracted number of $mcbitnum bits\n" if ($debug);;
- $ret{mcbitnum} = $mcbitnum;
- }
-
- elsif($_ =~ m/^C=\d+/) #### Message from array
- {
- $_ =~ s/C=//;
- $clockabs = $_ ;
- Debug "$name: extracted absolute clock $clockabs \n" if ($debug);
- $ret{clockabs} = $clockabs;
- } else {
- Debug "$name: unknown Message part $_" if ($debug);;
- }
- #print "$_\n";
- }
- $ret{pattern} = {%patternList};
- return %ret;
- }
- # Function which dispatches a message if needed.
- sub SIGNALduno_Dispatch($$$)
- {
- my ($hash, $rmsg, $dmsg) = @_;
- my $name = $hash->{NAME};
-
- if (!defined($dmsg))
- {
- Log3 $name, 5, "$name: (SIGNALduno_Dispatch) dmsg is undef. Skipping dispatch call";
- return;
- }
-
- Log3 $name, 5, "$name: converted Data to ($dmsg)";
- #Dispatch only if $dmsg is different from last $dmsg, or if 2 seconds are between transmits
- if ( ($hash->{DMSG} ne $dmsg) || ($hash->{TIME}+1 < time()) ) {
- $hash->{MSGCNT}++;
- $hash->{TIME} = time();
- $hash->{DMSG} = $dmsg;
- my $event = 0;
- if (substr($dmsg,0,1) eq 'u') {
- $event = 1;
- }
- readingsSingleUpdate($hash, "state", $hash->{READINGS}{state}{VAL}, $event);
- $hash->{RAWMSG} = $rmsg;
- my %addvals = (RAWMSG => $rmsg, DMSG => $dmsg);
- Dispatch($hash, $dmsg, \%addvals); ## Dispatch to other Modules
-
- } else {
- Log3 $name, 4, "$name: Dropped ($dmsg) due to short time or equal msg";
- }
- }
- sub
- SIGNALduino_Parse_MS($$$$%)
- {
- my ($hash, $iohash, $name, $rmsg,%msg_parts) = @_;
- my $protocolid;
- my $syncidx=$msg_parts{syncidx};
- my $clockidx=$msg_parts{clockidx};
- my $protocol=undef;
- my $rawData=$msg_parts{rawData};
- my %patternList;
- #$patternList{$_} = $msg_parts{rawData}{$_] for keys %msg_parts{rawData};
- #$patternList = \%msg_parts{pattern};
- #Debug "Message splitted:";
- #Debug Dumper(\@msg_parts);
- my $debug = AttrVal($iohash->{NAME},"debug",0);
-
- if (defined($clockidx) and defined($syncidx))
- {
-
- ## Make a lookup table for our pattern index ids
- #Debug "List of pattern:";
- my $clockabs= $msg_parts{pattern}{$msg_parts{clockidx}};
- return undef if ($clockabs == 0);
- $patternList{$_} = round($msg_parts{pattern}{$_}/$clockabs,1) for keys %{$msg_parts{pattern}};
-
-
- #Debug Dumper(\%patternList);
- #my $syncfact = $patternList{$syncidx}/$patternList{$clockidx};
- #$syncfact=$patternList{$syncidx};
- #Debug "SF=$syncfact";
- #### Convert rawData in Message
- my $signal_length = length($rawData); # Length of data array
- ## Iterate over the data_array and find zero, one, float and sync bits with the signalpattern
- ## Find matching protocols
- my $id;
- my $message_dispatched=0;
- foreach $id (@{$hash->{msIdList}}) {
-
- my $valid=1;
- #$debug=1;
- Debug "Testing against Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}" if ($debug);
- # Check Clock if is it in range
- $valid=SIGNALduino_inTol($ProtocolListSIGNALduino{$id}{clockabs},$clockabs,$clockabs*0.30) if ($ProtocolListSIGNALduino{$id}{clockabs} > 0);
- Debug "validclock = $valid" if ($debug);
-
- next if (!$valid) ;
- my $bit_length = ($signal_length-(scalar @{$ProtocolListSIGNALduino{$id}{sync}}))/((scalar @{$ProtocolListSIGNALduino{$id}{one}} + scalar @{$ProtocolListSIGNALduino{$id}{zero}})/2);
- #Check calculated min length
- $valid = $valid && $ProtocolListSIGNALduino{$id}{length_min} <= $bit_length if (exists $ProtocolListSIGNALduino{$id}{length_min});
- #Check calculated max length
- $valid = $valid && $ProtocolListSIGNALduino{$id}{length_max} >= $bit_length if (exists $ProtocolListSIGNALduino{$id}{length_max});
- next if (!$valid) ;
- Debug "expecting $bit_length bits in signal" if ($debug && $valid);
- #Debug Dumper(@{$ProtocolListSIGNALduino{$id}{sync}});
- Debug "Searching in patternList: ".Dumper(\%patternList) if($debug);
- Debug "searching sync: @{$ProtocolListSIGNALduino{$id}{sync}}[0] @{$ProtocolListSIGNALduino{$id}{sync}}[1]" if($debug); # z.B. [1, -18]
- #$valid = $valid && SIGNALduino_inTol($patternList{$clockidx}, @{$ProtocolListSIGNALduino{$id}{sync}}[0], 3); #sync in tolerance
- #$valid = $valid && SIGNALduino_inTol($patternList{$syncidx}, @{$ProtocolListSIGNALduino{$id}{sync}}[1], 3); #sync in tolerance
-
- my $pstr;
- my %patternLookupHash=();
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{sync}},\%patternList,\$rawData)) >=0;
- Debug "Found matched sync with indexes: ($pstr)" if ($debug && $valid);
- $patternLookupHash{$pstr}="" if ($valid); ## Append Sync to our lookuptable
- my $syncstr=$pstr; # Store for later start search
- Debug "sync not found " if (!$valid && $debug); # z.B. [1, -18]
- next if (!$valid) ;
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList,\$rawData)) >=0;
- Debug "Found matched one with indexes: ($pstr)" if ($debug && $valid);
- $patternLookupHash{$pstr}="1" if ($valid); ## Append Sync to our lookuptable
- #Debug "added $pstr " if ($debug && $valid);
- Debug "one pattern not found" if ($debug && !$valid);
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList,\$rawData)) >=0;
- Debug "Found matched zero with indexes: ($pstr)" if ($debug && $valid);
- $patternLookupHash{$pstr}="0" if ($valid); ## Append Sync to our lookuptable
- Debug "zero pattern not found" if ($debug && !$valid);
- #Debug "added $pstr " if ($debug && $valid);
- next if (!$valid) ;
- #Debug "Pattern Lookup Table".Dumper(%patternLookupHash);
- ## Check somethin else
-
- #Anything seems to be valid, we can start decoding this.
- Log3 $name, 4, "$name: Matched MS Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}" if ($valid);
- my $signal_width= @{$ProtocolListSIGNALduino{$id}{one}};
- #Debug $signal_width;
-
-
- my @bit_msg; # array to store decoded signal bits
- #for (my $i=index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{sync}}))+$signal_width;$i<length($rawData);$i+=$signal_width)
- #for (my $i=scalar@{$ProtocolListSIGNALduino{$id}{sync}};$i<length($rawData);$i+=$signal_width)
- my $message_start =index($rawData,$syncstr)+length($syncstr);
- Log3 $name, 5, "$name: Starting demodulation at Position $message_start";
-
- for (my $i=$message_start;$i<length($rawData);$i+=$signal_width)
- {
- my $sig_str= substr($rawData,$i,$signal_width);
- #Log3 $name, 5, "demodulating $sig_str";
- #Debug $patternLookupHash{substr($rawData,$i,$signal_width)}; ## Get $signal_width number of chars from raw data string
- if (exists $patternLookupHash{$sig_str}) { ## Add the bits to our bit array
- push(@bit_msg,$patternLookupHash{$sig_str})
- } else {
- Log3 $name, 5, "$name: Found wrong signalpattern, catched ".scalar @bit_msg." bits, aborting demodulation";
- last;
- }
- }
-
-
- Debug "$name: decoded message raw (@bit_msg), ".@bit_msg." bits\n" if ($debug);;
-
- my ($rcode,@retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$name,@bit_msg);
- next if (!$rcode);
- #Log3 $name, 5, "$name: postdemodulation value @retvalue";
-
- @bit_msg = @retvalue;
- undef(@retvalue); undef($rcode);
- my $padwith = defined($ProtocolListSIGNALduino{$id}{paddingbits}) ? $ProtocolListSIGNALduino{$id}{paddingbits} : 4;
-
- my $i=0;
- while (scalar @bit_msg % $padwith > 0) ## will pad up full nibbles per default or full byte if specified in protocol
- {
- push(@bit_msg,'0');
- $i++;
- }
- Debug "$name padded $i bits to bit_msg array" if ($debug);
-
- #my $logmsg = SIGNALduino_padbits(@bit_msg,$padwith);
-
- #Check converted message against lengths
- $valid = $valid && $ProtocolListSIGNALduino{$id}{length_min} <= scalar @bit_msg if (defined($ProtocolListSIGNALduino{$id}{length_min}));
- $valid = $valid && $ProtocolListSIGNALduino{$id}{length_max} >= scalar @bit_msg if (defined($ProtocolListSIGNALduino{$id}{length_max}));
- next if (!$valid);
-
- #my $dmsg = sprintf "%02x", oct "0b" . join "", @bit_msg; ## Array -> String -> bin -> hex
- my $dmsg = SIGNALduino_b2h(join "", @bit_msg);
- $dmsg = "$dmsg"."$ProtocolListSIGNALduino{$id}{postamble}" if (defined($ProtocolListSIGNALduino{$id}{postamble}));
- $dmsg = "$ProtocolListSIGNALduino{$id}{preamble}"."$dmsg" if (defined($ProtocolListSIGNALduino{$id}{preamble}));
-
- Log3 $name, 4, "$name: Decoded MS Protocol id $id dmsg $dmsg length " . scalar @bit_msg;
-
-
- #my ($rcode,@retvalue) = SIGNALduino_callsub('preDispatchfunc',$ProtocolListSIGNALduino{$id}{preDispatchfunc},$name,$dmsg);
- #next if (!$rcode);
- #$dmsg = @retvalue;
- #undef(@retvalue); undef($rcode);
-
-
- my $modulematch;
- if (defined($ProtocolListSIGNALduino{$id}{modulematch})) {
- $modulematch = $ProtocolListSIGNALduino{$id}{modulematch};
- }
- if (!defined($modulematch) || $dmsg =~ m/$modulematch/) {
- Debug "$name: dispatching now msg: $dmsg" if ($debug);
- SIGNALduno_Dispatch($hash,$rmsg,$dmsg);
- $message_dispatched=1;
- }
- }
-
- return 0 if (!$message_dispatched);
-
- return 1;
-
- }
- }
- ## //Todo: check list as reference
- sub SIGNALduino_padbits(\@$)
- {
- my $i=@{$_[0]} % $_[1];
- while (@{$_[0]} % $_[1] > 0) ## will pad up full nibbles per default or full byte if specified in protocol
- {
- push(@{$_[0]},'0');
- }
- return " padded $i bits to bit_msg array";
- }
- # - - - - - - - - - - - -
- #=item SIGNALduino_getProtoProp()
- #This functons, will return a value from the Protocolist and check if it is defined
- #
- # returns "" if the var is not defined
- # =cut
- # $id, $propertyname,
- sub SIGNALduino_getProtoProp($$)
- {
- my $id = shift;
- my $propNameLst = shift;
- return $ProtocolListSIGNALduino{$id}{$propNameLst} if defined($ProtocolListSIGNALduino{$id}{$propNameLst});
- return undef;
- }
- sub SIGNALduino_Parse_MU($$$$@)
- {
- my ($hash, $iohash, $name, $rmsg,%msg_parts) = @_;
- my $protocolid;
- my $clockidx=$msg_parts{clockidx};
- my $protocol=undef;
- my $rawData;
- my %patternListRaw;
- my $message_dispatched=0;
-
- my $debug = AttrVal($iohash->{NAME},"debug",0);
-
- Debug "$name: processing unsynced message\n" if ($debug);
- #my $clockabs; #Clock will be fetched from Protocol
- #$patternListRaw{$_} = floor($msg_parts{pattern}{$_}/$clockabs) for keys $msg_parts{pattern};
- $patternListRaw{$_} = $msg_parts{pattern}{$_} for keys %{$msg_parts{pattern}};
-
- if (defined($clockidx))
- {
-
- ## Make a lookup table for our pattern index ids
- #Debug "List of pattern:"; #Debug Dumper(\%patternList);
- ## Find matching protocols
- my $id;
- foreach $id (@{$hash->{muIdList}}) {
-
- my $valid=1;
- my $clockabs= $ProtocolListSIGNALduino{$id}{clockabs};
- my %patternList;
- $rawData=$msg_parts{rawData};
- if (exists($ProtocolListSIGNALduino{$id}{filterfunc}))
- {
- my $method = $ProtocolListSIGNALduino{$id}{filterfunc};
- if (!exists &$method)
- {
- Log3 $name, 5, "$name: Error: Unknown filtermethod=$method. Please define it in file $0";
- next;
- } else {
- Log3 $name, 5, "$name: applying filterfunc $method";
- no strict "refs";
- (my $count_changes,$rawData,my %patternListRaw_tmp) = $method->($name,$id,$rawData,%patternListRaw);
- use strict "refs";
- %patternList = map { $_ => round($patternListRaw_tmp{$_}/$clockabs,1) } keys %patternListRaw_tmp;
- }
- } else {
- %patternList = map { $_ => round($patternListRaw{$_}/$clockabs,1) } keys %patternListRaw;
- }
-
- my $signal_length = length($rawData); # Length of data array
-
- my @keys = sort { $patternList{$a} <=> $patternList{$b} } keys %patternList;
- #Debug Dumper(\%patternList);
- #Debug Dumper(@keys);
- #$debug=1;
-
- Debug "Testing against Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}" if ($debug);
-
- # $valid=SIGNALduino_inTol($ProtocolListSIGNALduino{$id}{clockabs},$clockabs,$clockabs*0.30) if ($ProtocolListSIGNALduino{$id}{clockabs} > 0);
- next if (!$valid) ;
-
- my $bit_length = ($signal_length/((scalar @{$ProtocolListSIGNALduino{$id}{one}} + scalar @{$ProtocolListSIGNALduino{$id}{zero}})/2));
- Debug "Expect $bit_length bits in message" if ($valid && $debug);
- #Check calculated min length
- #$valid = $valid && $ProtocolListSIGNALduino{$id}{length_min} <= $bit_length if (exists $ProtocolListSIGNALduino{$id}{length_min});
- #Check calculated max length
- #$valid = $valid && $ProtocolListSIGNALduino{$id}{length_max} >= $bit_length if (exists $ProtocolListSIGNALduino{$id}{length_max});
- #next if (!$valid) ;
- #Debug "expecting $bit_length bits in signal" if ($debug && $valid);
- Debug "Searching in patternList: ".Dumper(\%patternList) if($debug);
- next if (!$valid) ;
-
- my %patternLookupHash=();
- #Debug "phash:".Dumper(%patternLookupHash);
- my $pstr="";
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList,\$rawData)) >=0;
- Debug "Found matched one" if ($debug && $valid);
-
- my $oneStr=$pstr if ($valid);
- $patternLookupHash{$pstr}="1" if ($valid); ## Append one to our lookuptable
- Debug "added $pstr " if ($debug && $valid);
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList,\$rawData)) >=0;
- Debug "Found matched zero" if ($debug && $valid);
- my $zeroStr=$pstr if ($valid);
- $patternLookupHash{$pstr}="0" if ($valid); ## Append zero to our lookuptable
- Debug "added $pstr " if ($debug && $valid);
- if (defined($ProtocolListSIGNALduino{$id}{float}))
- {
- $valid = $valid && ($pstr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{float}},\%patternList,\$rawData)) >=0;
- Debug "Found matched float" if ($debug && $valid);
- $patternLookupHash{$pstr}="F" if ($valid); ## Append float to our lookuptable
- Debug "added $pstr " if ($debug && $valid);
- }
- next if (!$valid) ;
- #Debug "Pattern Lookup Table".Dumper(%patternLookupHash);
- ## Check somethin else
-
- #Anything seems to be valid, we can start decoding this.
- Log3 $name, 4, "$name: Fingerprint for MU Protocol id $id -> $ProtocolListSIGNALduino{$id}{name} matches, trying to demodulate" if ($valid);
- my $signal_width= @{$ProtocolListSIGNALduino{$id}{one}};
- #Debug $signal_width;
-
- my @bit_msg=(); # array to store decoded signal bits
-
- my $message_start=0 ;
- my @msgStartLst;
- my $startStr="";
- my $start_regex;
- #my $oneStr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList,\$rawData);
- #my $zeroStr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList,\$rawData);
- if (@msgStartLst = SIGNALduino_getProtoProp($id,"start"))
- {
- Debug "msgStartLst: ".Dumper(@msgStartLst) if ($debug);
-
- if ( ($startStr=SIGNALduino_PatternExists($hash,@msgStartLst,\%patternList,\$rawData)) eq -1)
- {
- Log3 $name, 5, "$name: start pattern for MU Protocol id $id -> $ProtocolListSIGNALduino{$id}{name} mismatches, aborting" ;
- $valid=0;
- next;
- };
- }
- $start_regex="$startStr($oneStr|$zeroStr)";
- Debug "Regex is: $start_regex" if ($debug);
-
- $rawData =~ /$start_regex/;
- if (defined($-[0] && $-[0] > 0)) {
- $message_start=$-[0]+ length($startStr);
- } else {
- undef($message_start);
- }
- undef @msgStartLst;
-
- #for (my $i=index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{sync}}))+$signal_width;$i<length($rawData);$i+=$signal_width)
- Debug "Message starts at $message_start - length of data is ".length($rawData) if ($debug);
- next if (!defined($message_start));
- Log3 $name, 5, "$name: Starting demodulation at Position $message_start";
- #my $onepos= index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList));
- #my $zeropos=index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList));
- #Log3 $name, 3, "op=$onepos zp=$zeropos";
- #Debug "phash:".Dumper(%patternLookupHash);
-
- my $padwith = defined($ProtocolListSIGNALduino{$id}{paddingbits}) ? $ProtocolListSIGNALduino{$id}{paddingbits} : 4;
-
- for (my $i=$message_start;$i<=length($rawData)-$signal_width;$i+=$signal_width)
- {
-
- my $sig_str= substr($rawData,$i,$signal_width);
- Debug "$name: i=$i search=$sig_str" if ($debug);
- $valid=1; # Set valid to 1 for every loop
- #Debug $patternLookupHash{substr($rawData,$i,$signal_width)}; ## Get $signal_width number of chars from raw data string
- if (exists $patternLookupHash{$sig_str})
- {
- my $bit = $patternLookupHash{$sig_str};
-
- push(@bit_msg,$bit) if (looks_like_number($bit)) ; ## Add the bits to our bit array
- }
- if (!exists $patternLookupHash{$sig_str} || $i+$signal_width>length($rawData)-$signal_width) ## Dispatch if last signal or unknown data
- {
- Debug "$name: demodulated message raw (@bit_msg), ".@bit_msg." bits\n" if ($debug);
- #Check converted message against lengths
- $valid = $valid && $ProtocolListSIGNALduino{$id}{length_max} >= scalar @bit_msg if (defined($ProtocolListSIGNALduino{$id}{length_max}));
- $valid = $valid && $ProtocolListSIGNALduino{$id}{length_min} <= scalar @bit_msg if (defined($ProtocolListSIGNALduino{$id}{length_min}));
-
- #next if (!$valid); ## Last chance to try next protocol if there is somethin invalid
- if ($valid) {
-
- my ($rcode,@retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$name,@bit_msg);
- next if (!$rcode);
- #Log3 $name, 5, "$name: postdemodulation value @retvalue";
-
- @bit_msg = @retvalue;
- undef(@retvalue); undef($rcode);
-
-
- while (scalar @bit_msg % $padwith > 0) ## will pad up full nibbles per default or full byte if specified in protocol
- {
- push(@bit_msg,'0');
- Debug "$name: padding 0 bit to bit_msg array" if ($debug);
- }
-
- Log3 $name, 5, "$name: dispatching bits: @bit_msg";
- my $dmsg = SIGNALduino_b2h(join "", @bit_msg);
- $dmsg =~ s/^0+// if (defined($ProtocolListSIGNALduino{$id}{remove_zero}));
- $dmsg = "$dmsg"."$ProtocolListSIGNALduino{$id}{postamble}" if (defined($ProtocolListSIGNALduino{$id}{postamble}));
- $dmsg = "$ProtocolListSIGNALduino{$id}{preamble}"."$dmsg" if (defined($ProtocolListSIGNALduino{$id}{preamble}));
-
- Log3 $name, 4, "$name: decoded matched MU Protocol id $id dmsg $dmsg length " . scalar @bit_msg;
-
- my $modulematch;
- if (defined($ProtocolListSIGNALduino{$id}{modulematch})) {
- $modulematch = $ProtocolListSIGNALduino{$id}{modulematch};
- }
- if (!defined($modulematch) || $dmsg =~ m/$modulematch/) {
- Debug "$name: dispatching now msg: $dmsg" if ($debug);
- SIGNALduno_Dispatch($hash,$rmsg,$dmsg);
- $message_dispatched=1;
- }
- } else {
- if ($debug)
- {
- my $debugstr;
- $debugstr.=$ProtocolListSIGNALduino{$id}{length_min} if defined($ProtocolListSIGNALduino{$id}{length_min});
- $debugstr.="/";
- $debugstr.=$ProtocolListSIGNALduino{$id}{length_max} if defined($ProtocolListSIGNALduino{$id}{length_max});
-
- Debug "$name: length ($debugstr) does not match (@bit_msg), ".@bit_msg." bits\n";
- }
-
- }
- @bit_msg=(); # clear bit_msg array
-
- #Find next position of valid signal (skip invalid pieces)
- my $regex=".{$i}".$start_regex;
- Debug "$name: searching new start with ($regex)\n" if ($debug);
-
- $rawData =~ /$regex/;
- if (defined($-[0]) && ($-[0] > 0)) {
- #$i=$-[0]+ $i+ length($startStr);
- $i=$-[0]+ $i;
-
- $i=$i-$signal_width if ($i>0 && length($startStr) == 0); #Todo:
- Debug "$name: found restart at Position $i ($regex)\n" if ($debug);
- } else {
- last;
- }
-
- #if ($startStr)
- #{
- # $i= index($rawData,$startStr,$i);
- # } else {
- # $i = (index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList),$i+$signal_width) < index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList),$i+$signal_width) ? index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{one}},\%patternList),$i+$signal_width) : index($rawData,SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{zero}},\%patternList),$i+$signal_width));
- # $i-=$signal_width if ($i<length($rawData)-$signal_width) ;
- #
- # }
- # last if ($i <=-1);
- Log3 $name, 5, "$name: restarting demodulation at Position $i+$signal_width" if ($debug);
-
- }
- }
-
- #my $dmsg = sprintf "%02x", oct "0b" . join "", @bit_msg; ## Array -> String -> bin -> hex
- }
- return 0 if (!$message_dispatched);
-
- return 1;
- }
- }
- sub
- SIGNALduino_Parse_MC($$$$@)
- {
- my ($hash, $iohash, $name, $rmsg,%msg_parts) = @_;
- my $clock=$msg_parts{clockabs}; ## absolute clock
- my $rawData=$msg_parts{rawData};
- my $bitData;
- my $dmsg;
- my $message_dispatched=0;
- my $debug = AttrVal($iohash->{NAME},"debug",0);
-
- return undef if (!$clock);
- #my $protocol=undef;
- #my %patternListRaw = %msg_parts{patternList};
-
- Debug "$name: processing manchester messag len:".length($rawData) if ($debug);
-
- my $hlen = length($rawData);
- my $blen = $hlen * 4;
- my $id;
-
- my $rawDataInverted;
- ($rawDataInverted = $rawData) =~ tr/0123456789ABCDEF/FEDCBA9876543210/; # Some Manchester Data is inverted
-
- foreach $id (@{$hash->{mcIdList}}) {
- if ( $clock >$ProtocolListSIGNALduino{$id}{clockrange}[0] and $clock <$ProtocolListSIGNALduino{$id}{clockrange}[1] and length($rawData)*4 >= $ProtocolListSIGNALduino{$id}{length_min} )
- {
- Debug "clock and min length matched" if ($debug);
- Log3 $name, 4, "$name: Found manchester Protocol id $id clock $clock -> $ProtocolListSIGNALduino{$id}{name}";
-
- if (exists($ProtocolListSIGNALduino{$id}{polarity}) && ($ProtocolListSIGNALduino{$id}{polarity} eq 'invert') && (!defined($hash->{version}) || substr($hash->{version},0,6) ne 'V 3.2.'))
- # todo && substr($hash->{version},0,6) ne 'V 3.2.') # bei version V 3.2. nicht invertieren
- {
- $bitData= unpack("B$blen", pack("H$hlen", $rawDataInverted));
- } else {
- $bitData= unpack("B$blen", pack("H$hlen", $rawData));
- }
- Debug "$name: extracted data $bitData (bin)\n" if ($debug); ## Convert Message from hex to bits
- Log3 $name, 5, "$name: extracted data $bitData (bin)";
-
- my $method = $ProtocolListSIGNALduino{$id}{method};
- if (!exists &$method)
- {
- Log3 $name, 5, "$name: Error: Unknown function=$method. Please define it in file $0";
- } else {
- my ($rcode,$res) = $method->($name,$bitData,$id);
- if ($rcode != -1) {
- $dmsg = $res;
- $dmsg=$ProtocolListSIGNALduino{$id}{preamble}.$dmsg if (defined($ProtocolListSIGNALduino{$id}{preamble}));
- my $modulematch;
- if (defined($ProtocolListSIGNALduino{$id}{modulematch})) {
- $modulematch = $ProtocolListSIGNALduino{$id}{modulematch};
- }
- if (!defined($modulematch) || $dmsg =~ m/$modulematch/) {
- SIGNALduno_Dispatch($hash,$rmsg,$dmsg);
- $message_dispatched=1;
- }
- } else {
- Log3 $name, 5, "$name: protocol does not match return from method: ($res)" if ($debug);
- }
- }
- }
-
- }
- return 0 if (!$message_dispatched);
- return 1;
- }
- sub
- SIGNALduino_Parse($$$$@)
- {
- my ($hash, $iohash, $name, $rmsg, $initstr) = @_;
- #print Dumper(\%ProtocolListSIGNALduino);
-
- return undef if !($rmsg=~ s/^\002(M.;.*;)\003/$1/); ## Check if a Data Message arrived and if it's complete (start & end control char are received)
- # cut off start end end character from message for further processing they are not needed
- if (defined($hash->{keepalive})) {
- $hash->{keepalive}{ok} = 1;
- $hash->{keepalive}{retry} = 0;
- }
-
- my $debug = AttrVal($iohash->{NAME},"debug",0);
-
-
- Debug "$name: incomming message: ($rmsg)\n" if ($debug);
-
- my %signal_parts=SIGNALduino_Split_Message($rmsg,$name); ## Split message and save anything in an hash %signal_parts
- #Debug "raw data ". $signal_parts{rawData};
-
-
- my $dispatched;
- # Message Synced type -> M#
- if (@{$hash->{msIdList}} && $rmsg=~ m/^MS;(P\d=-?\d+;){3,8}D=\d+;CP=\d;SP=\d;/)
- {
- $dispatched= SIGNALduino_Parse_MS($hash, $iohash, $name, $rmsg,%signal_parts);
- }
- # Message unsynced type -> MU
- elsif (@{$hash->{muIdList}} && $rmsg=~ m/^MU;(P\d=-?\d+;){3,8}D=\d+;CP=\d;/)
- {
- $dispatched= SIGNALduino_Parse_MU($hash, $iohash, $name, $rmsg,%signal_parts);
- }
- # Manchester encoded Data -> MC
- elsif (@{$hash->{mcIdList}} && $rmsg=~ m/^MC;.*;/)
- {
- $dispatched= SIGNALduino_Parse_MC($hash, $iohash, $name, $rmsg,%signal_parts);
- }
- else {
- Debug "$name: unknown Messageformat, aborting\n" if ($debug);
- return undef;
- }
-
- if ( AttrVal($hash->{NAME},"verbose","0") > 4 && !$dispatched)
- {
- my $notdisplist;
- my @lines;
- if (defined($hash->{unknownmessages}))
- {
- $notdisplist=$hash->{unknownmessages};
- @lines = split ('#', $notdisplist); # or whatever
- }
- push(@lines,FmtDateTime(time())."-".$rmsg);
- shift(@lines)if (scalar @lines >25);
- $notdisplist = join('#',@lines);
- $hash->{unknownmessages}=$notdisplist;
- return undef;
- #Todo compare Sync/Clock fact and length of D= if equal, then it's the same protocol!
- }
- }
- #####################################
- sub
- SIGNALduino_Ready($)
- {
- my ($hash) = @_;
- if ($hash->{STATE} eq 'disconnected') {
- $hash->{DevState} = 'disconnected';
- return DevIo_OpenDev($hash, 1, "SIGNALduino_DoInit", 'SIGNALduino_Connect')
- }
-
- # This is relevant for windows/USB only
- my $po = $hash->{USBDev};
- my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
- if($po) {
- ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
- }
- return ($InBytes && $InBytes>0);
- }
- ########################
- sub
- SIGNALduino_SimpleWrite(@)
- {
- my ($hash, $msg, $nonl) = @_;
- return if(!$hash);
- if($hash->{TYPE} eq "SIGNALduino_RFR") {
- # Prefix $msg with RRBBU and return the corresponding SIGNALduino hash.
- ($hash, $msg) = SIGNALduino_RFR_AddPrefix($hash, $msg);
- }
- my $name = $hash->{NAME};
- Log3 $name, 5, "$name SW: $msg";
- $msg .= "\n" unless($nonl);
- $hash->{USBDev}->write($msg) if($hash->{USBDev});
- syswrite($hash->{TCPDev}, $msg) if($hash->{TCPDev});
- syswrite($hash->{DIODev}, $msg) if($hash->{DIODev});
- # Some linux installations are broken with 0.001, T01 returns no answer
- select(undef, undef, undef, 0.01);
- }
- sub
- SIGNALduino_Attr(@)
- {
- my ($cmd,$name,$aName,$aVal) = @_;
- my $hash = $defs{$name};
- my $debug = AttrVal($name,"debug",0);
-
- $aVal= "" if (!defined($aVal));
- Log3 $name, 4, "$name: Calling Getting Attr sub with args: $cmd $aName = $aVal";
-
- if( $aName eq "Clients" ) { ## Change clientList
- $hash->{Clients} = $aVal;
- $hash->{Clients} = $clientsSIGNALduino if( !$hash->{Clients}) ; ## Set defaults
- return "Setting defaults";
- } elsif( $aName eq "MatchList" ) { ## Change matchList
- my $match_list;
- if( $cmd eq "set" ) {
- $match_list = eval $aVal;
- if( $@ ) {
- Log3 $name, 2, $name .": $aVal: ". $@;
- }
- }
-
- if( ref($match_list) eq 'HASH' ) {
- $hash->{MatchList} = $match_list;
- } else {
- $hash->{MatchList} = \%matchListSIGNALduino; ## Set defaults
- Log3 $name, 2, $name .": $aVal: not a HASH using defaults" if( $aVal );
- }
- }
- elsif ($aName eq "verbose")
- {
- Log3 $name, 3, "$name: setting Verbose to: " . $aVal;
- $hash->{unknownmessages}="" if $aVal <4;
-
- }
- elsif ($aName eq "debug")
- {
- $debug = $aVal;
- Log3 $name, 3, "$name: setting debug to: " . $debug;
- }
- elsif ($aName eq "whitelist_IDs")
- {
- SIGNALduino_IdList($hash, $name, $aVal);
- }
-
- return undef;
- }
- sub SIGNALduino_IdList($$$)
- {
- my ($hash, $name, $aVal) = @_;
- my @msIdList = ();
- my @muIdList = ();
- my @mcIdList = ();
- my %WhitelistIDs;
- my $wflag = 0;
- if (defined($aVal) && length($aVal)>0)
- {
- if (substr($aVal,0 ,1) eq '#') {
- Log3 $name, 3, "Attr whitelist deaktiviert: $aVal";
- }
- else {
- %WhitelistIDs = map { $_ => 1 } split(",", $aVal);
- #my $w = join ', ' => map "$_" => keys %WhitelistIDs;
- #Log3 $name, 3, "Attr whitelist $w";
- $wflag = 1;
- }
- }
- my $id;
- foreach $id (keys %ProtocolListSIGNALduino)
- {
- next if ($id eq 'id');
- if ($wflag == 1 && !defined($WhitelistIDs{$id}))
- {
- #Log3 $name, 3, "skip ID $id";
- next;
- }
-
- if (exists ($ProtocolListSIGNALduino{$id}{format}) && $ProtocolListSIGNALduino{$id}{format} eq "manchester")
- {
- push (@mcIdList, $id);
- }
- elsif (exists $ProtocolListSIGNALduino{$id}{sync})
- {
- push (@msIdList, $id);
- }
- elsif (exists ($ProtocolListSIGNALduino{$id}{clockabs}))
- {
- push (@muIdList, $id);
- }
- }
- @msIdList = sort @msIdList;
- @muIdList = sort @muIdList;
- @mcIdList = sort @mcIdList;
- Log3 $name, 3, "$name: IDlist MS @msIdList";
- Log3 $name, 3, "$name: IDlist MU @muIdList";
- Log3 $name, 3, "$name: IDlist MC @mcIdList";
-
- $hash->{msIdList} = \@msIdList;
- $hash->{muIdList} = \@muIdList;
- $hash->{mcIdList} = \@mcIdList;
- }
- sub SIGNALduino_callsub
- {
- my $funcname =shift;
- my $method = shift;
- my $name = shift;
- my @args = @_;
-
-
- if ( defined $method && defined &$method )
- {
- Log3 $name, 5, "$name: applying $funcname method $method";
- #Log3 $name, 5, "$name: value bevore $funcname: @args";
-
- my @returnvalues = $method->(@args) ;
-
- Log3 $name, 5, "$name: modified value after $funcname: @returnvalues";
- return (1,@returnvalues);
- } elsif (defined $method ) {
- Log3 $name, 5, "$name: Error: Unknown method $funcname Please check definition";
- return (0,undef);
- }
- return (1,@args);
- }
- # calculates the hex (in bits) and adds it at the beginning of the message
- # input = @list
- # output = @list
- sub SIGNALduino_lengtnPrefix
- {
- my $msg = join("",@_);
- #$msg = unpack("B8", pack("N", length($msg))).$msg;
- $msg=sprintf('%08b', length($msg)).$msg;
-
- return split("",$msg);
- }
- sub SIGNALduino_bit2Arctec
- {
- my $msg = join("",@_);
- # Convert 0 -> 01 1 -> 10 to be compatible with IT Module
- $msg =~ s/0/z/g;
- $msg =~ s/1/10/g;
- $msg =~ s/z/01/g;
- return split("",$msg);
- }
- sub SIGNALduino_ITV1_tristateToBit($)
- {
- my ($msg) = @_;
- # Convert 0 -> 00 1 -> 11 F => 01 to be compatible with IT Module
- $msg =~ s/0/00/g;
- $msg =~ s/1/11/g;
- $msg =~ s/F/01/g;
- $msg =~ s/D/10/g;
-
- return $msg;
- }
- sub SIGNALduino_OSV2()
- {
- my ($name,$bitData,$id) = @_;
-
- my $preamble_pos;
- my $message_end;
- my $message_length;
-
- #$bitData =~ tr/10/01/;
- if ($bitData =~ m/^.?(01){12,17}.?10011001/)
- { # Valid OSV2 detected!
- #$preamble_pos=index($bitData,"10011001",24);
- $preamble_pos=$+[1];
-
- Log3 $name, 4, "$name: OSV2 protocol detected: preamble_pos = $preamble_pos";
- return return (-1," sync not found") if ($preamble_pos <=24);
-
- $message_end=$-[1] if ($bitData =~ m/^.{44,}(01){16,17}.?10011001/); #Todo regex .{44,} 44 should be calculated from $preamble_pos+ min message lengh (44)
- if (!defined($message_end) || $message_end < $preamble_pos) {
- $message_end = length($bitData);
- } else {
- $message_end += 16;
- Log3 $name, 4, "$name: OSV2 message end pattern found at pos $message_end lengthBitData=".length($bitData);
- }
- $message_length = ($message_end - $preamble_pos)/2;
- return (-1," message is to short") if (defined($ProtocolListSIGNALduino{$id}{length_min}) && $message_length < $ProtocolListSIGNALduino{$id}{length_min} );
- return (-1," message is to long") if (defined($ProtocolListSIGNALduino{$id}{length_max}) && $message_length > $ProtocolListSIGNALduino{$id}{length_max} );
-
- my $idx=0;
- my $osv2bits="";
- my $osv2hex ="";
-
- for ($idx=$preamble_pos;$idx<$message_end;$idx=$idx+16)
- {
- if ($message_end-$idx < 8 )
- {
- last;
- }
- my $osv2byte = "";
- $osv2byte=NULL;
- $osv2byte=substr($bitData,$idx,16);
- my $rvosv2byte="";
-
- for (my $p=0;$p<length($osv2byte);$p=$p+2)
- {
- $rvosv2byte = substr($osv2byte,$p,1).$rvosv2byte;
- }
- $rvosv2byte =~ tr/10/01/;
-
- if (length($rvosv2byte) eq 8) {
- $osv2hex=$osv2hex.sprintf('%02X', oct("0b$rvosv2byte")) ;
- } else {
- $osv2hex=$osv2hex.sprintf('%X', oct("0b$rvosv2byte")) ;
- }
- $osv2bits = $osv2bits.$rvosv2byte;
- }
- $osv2hex = sprintf("%02X", length($osv2hex)*4).$osv2hex;
- Log3 $name, 4, "$name: OSV2 protocol converted to hex: ($osv2hex) with length (".(length($osv2hex)*4).") bits";
- #$found=1;
- #$dmsg=$osv2hex;
- return (1,$osv2hex);
- }
- elsif ($bitData =~ m/^.?(1){16,24}0101/) { # Valid OSV3 detected!
- $preamble_pos = index($bitData, '0101', 16);
- $message_end = length($bitData);
- $message_length = $message_end - ($preamble_pos+4);
- Log3 $name, 4, "$name: OSV3 protocol detected: preamble_pos = $preamble_pos, message_length = $message_length";
-
- my $idx=0;
- #my $osv3bits="";
- my $osv3hex ="";
-
- for ($idx=$preamble_pos+4;$idx<length($bitData);$idx=$idx+4)
- {
- if (length($bitData)-$idx < 4 )
- {
- last;
- }
- my $osv3nibble = "";
- $osv3nibble=NULL;
- $osv3nibble=substr($bitData,$idx,4);
- my $rvosv3nibble="";
-
- for (my $p=0;$p<length($osv3nibble);$p++)
- {
- $rvosv3nibble = substr($osv3nibble,$p,1).$rvosv3nibble;
- }
- $osv3hex=$osv3hex.sprintf('%X', oct("0b$rvosv3nibble"));
- #$osv3bits = $osv3bits.$rvosv3nibble;
- }
- Log3 $name, 4, "$name: OSV3 protocol = $osv3hex";
- my $korr = 10;
- # Check if nibble 1 is A
- if (substr($osv3hex,1,1) ne 'A')
- {
- my $n1=substr($osv3hex,1,1);
- $korr = hex(substr($osv3hex,3,1));
- substr($osv3hex,1,1,'A'); # nibble 1 = A
- substr($osv3hex,3,1,$n1); # nibble 3 = nibble1
- }
- # Korrektur nibble
- my $insKorr = sprintf('%X', $korr);
- # Check for ending 00
- if (substr($osv3hex,-2,2) eq '00')
- {
- #substr($osv3hex,1,-2); # remove 00 at end
- $osv3hex = substr($osv3hex, 0, length($osv3hex)-2);
- }
- my $osv3len = length($osv3hex);
- $osv3hex .= '0';
- my $turn0 = substr($osv3hex,5, $osv3len-4);
- my $turn = '';
- for ($idx=0; $idx<$osv3len-5; $idx=$idx+2) {
- $turn = $turn . substr($turn0,$idx+1,1) . substr($turn0,$idx,1);
- }
- $osv3hex = substr($osv3hex,0,5) . $insKorr . $turn;
- $osv3hex = substr($osv3hex,0,$osv3len+1);
- $osv3hex = sprintf("%02X", length($osv3hex)*4).$osv3hex;
- Log3 $name, 4, "$name: OSV3 protocol converted to hex: ($osv3hex) with length (".((length($osv3hex)-2)*4).") bits";
- #$found=1;
- #$dmsg=$osv2hex;
- return (1,$osv3hex);
-
- }
- return (-1,undef);
- }
- sub SIGNALduino_OSV1()
- {
- my ($name,$bitData,$rawData) = @_;
-
- my $idx=0;
-
- my $osv1hex ;# ~hex('0x'.$rawData);
- #my $osv1bit = $bitData =~ tr/10/01/r;
- my $osv1bit;
- ($osv1bit = $bitData) =~ tr/10/01/;
- #Log3 $name, 5, "$name: OSV1 protocol converted from ($bitData) to bit: ($osv1bit)" ;
- $osv1hex=sprintf("%02X", length($rawData)*4, $osv1hex).SIGNALduino_b2h($osv1bit);
- Log3 $name, 5, "$name: OSV1 protocol converted to hex: ($osv1hex) with length (".(length($rawData)*4).") bits \n";
- return (1,$osv1hex);
- }
- sub SIGNALduino_AS()
- {
- my ($name,$bitData,$id) = @_;
- my $debug = AttrVal($name,"debug",0);
-
- if(index($bitData,"1100",16) >= 0) # $rawData =~ m/^A{2,3}/)
- { # Valid AS detected!
- my $message_start = index($bitData,"1100",16);
- Debug "$name: AS protocol detected \n" if ($debug);
-
- my $message_end=index($bitData,"1100",$message_start+16);
- $message_end = length($bitData) if ($message_end == -1);
- my $message_length = $message_end - $message_start;
-
- return (-1," message is to short") if (defined($ProtocolListSIGNALduino{$id}{length_min}) && $message_length < $ProtocolListSIGNALduino{$id}{length_min} );
- return (-1," message is to long") if (defined($ProtocolListSIGNALduino{$id}{length_max}) && $message_length > $ProtocolListSIGNALduino{$id}{length_max} );
-
-
- my $msgbits =substr($bitData,$message_start);
-
- my $ashex=sprintf('%02X', oct("0b$msgbits"));
- Log3 $name, 5, "$name: AS protocol converted to hex: ($ashex) with length ($message_length) bits \n";
- return (1,$bitData);
- }
- return (-1,undef);
- }
- sub SIGNALduino_Hideki()
- {
- my ($name,$bitData,$id) = @_;
- my $debug = AttrVal($name,"debug",0);
-
- Debug "$name: search in $bitData \n" if ($debug);
- my $message_start = index($bitData,"10101110");
- if ($message_start >= 0 ) # 0x75 but in reverse order
- {
- Debug "$name: Hideki protocol detected \n" if ($debug);
- # Todo: Mindest Laenge fuer startpunkt vorspringen
- # Todo: Wiederholung auch an das Modul weitergeben, damit es dort geprueft werden kann
- my $message_end = index($bitData,"10101110",$message_start+71); # pruefen auf ein zweites 0x75, mindestens 72 bit nach 1. 0x75, da der Regensensor minimum 8 Byte besitzt je byte haben wir 9 bit
- $message_end = length($bitData) if ($message_end == -1);
- my $message_length = $message_end - $message_start;
-
- return (-1,"message is to short") if (defined($ProtocolListSIGNALduino{$id}{length_min}) && $message_length < $ProtocolListSIGNALduino{$id}{length_min} );
- return (-1,"message is to long") if (defined($ProtocolListSIGNALduino{$id}{length_max}) && $message_length > $ProtocolListSIGNALduino{$id}{length_max} );
-
- my $hidekihex;
- my $idx;
-
- for ($idx=$message_start; $idx<$message_end; $idx=$idx+9)
- {
- my $byte = "";
- $byte= substr($bitData,$idx,8); ## Ignore every 9th bit
- Debug "$name: byte in order $byte " if ($debug);
- $byte = scalar reverse $byte;
- Debug "$name: byte reversed $byte , as hex: ".sprintf('%X', oct("0b$byte"))."\n" if ($debug);
- $hidekihex=$hidekihex.sprintf('%02X', oct("0b$byte"));
- }
- Log3 $name, 4, "$name: hideki protocol converted to hex: $hidekihex with " .$message_length ." bits, messagestart $message_start";
- return (1,$hidekihex); ## Return only the original bits, include length
- }
- return (-1,"");
- }
- sub SIGNALduino_Maverick()
- {
- my ($name,$bitData,$id) = @_;
- my $debug = AttrVal($name,"debug",0);
- if ($bitData =~ m/^.*(101010101001100110010101).*/)
- { # Valid Maverick header detected
- my $header_pos=$+[1];
-
- Log3 $name, 4, "$name: Maverick protocol detected: header_pos = $header_pos";
- my $hex=SIGNALduino_b2h(substr($bitData,$header_pos,26*4));
-
- return (1,$hex); ## Return the bits unchanged in hex
- } else {
- return return (-1," header not found");
- }
- }
- sub SIGNALduino_SomfyRTS()
- {
- my ($name, $bitData, $rawData) = @_;
-
- #(my $negBits = $bitData) =~ tr/10/01/; # Todo: eventuell auf pack umstellen
- my $encData = SIGNALduino_b2h($bitData);
- #Log3 $name, 4, "$name: Somfy RTS protocol enc: $encData";
- return (1, $encData);
- }
- # - - - - - - - - - - - -
- #=item SIGNALduino_filterSign()
- #This functons, will act as a filter function. It will remove the sign from the pattern, and compress message and pattern
- #
- # Will return $count of combined values, modified $rawData , modified %patternListRaw,
- # =cut
- sub SIGNALduino_filterSign($$$%)
- {
- my ($name,$id,$rawData,%patternListRaw) = @_;
- my $debug = AttrVal($name,"debug",0);
- my %buckets;
- # Remove Sign
- %patternListRaw = map { $_ => abs($patternListRaw{$_})} keys %patternListRaw; ## remove sing from all
-
- my $intol=0;
- my $cnt=0;
- # compress pattern hash
- foreach my $key (keys %patternListRaw) {
-
- #print "chk:".$patternListRaw{$key};
- #print "\n";
- $intol=0;
- foreach my $b_key (keys %buckets){
- #print "with:".$buckets{$b_key};
- #print "\n";
-
- # $value - $set <= $tolerance
- if (SIGNALduino_inTol($patternListRaw{$key},$buckets{$b_key},$buckets{$b_key}*0.25))
- {
- #print"\t". $patternListRaw{$key}."($key) is intol of ".$buckets{$b_key}."($b_key) \n";
- $cnt++;
- eval "\$rawData =~ tr/$key/$b_key/";
- #if ($key == $msg_parts{clockidx})
- #{
- # $msg_pats{syncidx} = $buckets{$key};
- # }
- # elsif ($key == $msg_parts{syncidx})
- # {
- # $msg_pats{syncidx} = $buckets{$key};
- # }
-
- $buckets{$b_key} = ($buckets{$b_key} + $patternListRaw{$key}) /2;
- #print"\t recalc to ". $buckets{$b_key}."\n";
- delete ($patternListRaw{$key}); # deletes the compressed entry
- $intol=1;
- last;
- }
- }
- if ($intol == 0) {
- $buckets{$key}=abs($patternListRaw{$key});
- }
- }
- return ($cnt,$rawData, %patternListRaw);
- #print "rdata: ".$msg_parts{rawData}."\n";
- #print Dumper (%buckets);
- #print Dumper (%msg_parts);
- #modify msg_parts pattern hash
- #$patternListRaw = \%buckets;
- }
- # - - - - - - - - - - - -
- #=item SIGNALduino_compPattern()
- #This functons, will act as a filter function. It will remove the sign from the pattern, and compress message and pattern
- #
- # Will return $count of combined values, modified $rawData , modified %patternListRaw,
- # =cut
- sub SIGNALduino_compPattern($$$%)
- {
- my ($name,$id,$rawData,%patternListRaw) = @_;
- my $debug = AttrVal($name,"debug",0);
- my %buckets;
- # Remove Sign
- #%patternListRaw = map { $_ => abs($patternListRaw{$_})} keys %patternListRaw; ## remove sing from all
-
- my $intol=0;
- my $cnt=0;
- # compress pattern hash
- foreach my $key (keys %patternListRaw) {
-
- #print "chk:".$patternListRaw{$key};
- #print "\n";
- $intol=0;
- foreach my $b_key (keys %buckets){
- #print "with:".$buckets{$b_key};
- #print "\n";
-
- # $value - $set <= $tolerance
- if (SIGNALduino_inTol($patternListRaw{$key},$buckets{$b_key},$buckets{$b_key}*0.4))
- {
- #print"\t". $patternListRaw{$key}."($key) is intol of ".$buckets{$b_key}."($b_key) \n";
- $cnt++;
- eval "\$rawData =~ tr/$key/$b_key/";
- #if ($key == $msg_parts{clockidx})
- #{
- # $msg_pats{syncidx} = $buckets{$key};
- # }
- # elsif ($key == $msg_parts{syncidx})
- # {
- # $msg_pats{syncidx} = $buckets{$key};
- # }
-
- $buckets{$b_key} = ($buckets{$b_key} + $patternListRaw{$key}) /2;
- #print"\t recalc to ". $buckets{$b_key}."\n";
- delete ($patternListRaw{$key}); # deletes the compressed entry
- $intol=1;
- last;
- }
- }
- if ($intol == 0) {
- $buckets{$key}=$patternListRaw{$key};
- }
- }
- return ($cnt,$rawData, %patternListRaw);
- #print "rdata: ".$msg_parts{rawData}."\n";
- #print Dumper (%buckets);
- #print Dumper (%msg_parts);
- #modify msg_parts pattern hash
- #$patternListRaw = \%buckets;
- }
- #print Dumper (%msg_parts);
- #print "\n";
- #SIGNALduino_filterSign(%msg_parts);
- #print Dumper (%msg_parts);
- #print "\n";
- 1;
- =pod
- =item summary supports the same low-cost receiver for digital signals
- =item summary_DE Unterstützt den gleichnamigen Low-Cost Empfänger fuer digitale Signale
- =begin html
- <a name="SIGNALduino"></a>
- <h3>SIGNALduino</h3>
- <table>
- <tr><td>
- The SIGNALduino ia based on an idea from mdorenka published at <a
- href="http://forum.fhem.de/index.php/topic,17196.0.html">FHEM Forum</a>.
- With the opensource firmware (see this <a
- href="https://github.com/RFD-FHEM/SIGNALduino">link</a>) it is capable
- to receive and send different protocols over different medias. Currently are 433Mhz protocols implemented.
- <br><br>
- The following device support is currently available:
- <br><br>
- Wireless switches <br>
- ITv1 & ITv3/Elro and other brands using pt2263 or arctech protocol--> uses IT.pm<br>
- <br><br>
- Temperatur / humidity senso
- <ul>
- <li>PEARL NC7159, LogiLink WS0002,GT-WT-02,AURIOL,TCM97001, TCM27 and many more -> 14_CUL_TCM97001 </li>
- <li>Oregon Scientific v2 and v3 Sensors -> 41_OREGON.pm</li>
- <li>Temperatur / humidity sensors suppored -> 14_SD_WS07</li>
- <li>technoline WS 6750 and TX70DTH -> 14_SD_WS07</li>
- <li>Eurochon EAS 800z -> 14_SD_WS07</li>
- <li>CTW600, WH1080 -> 14_SD_WS09 </li>
- <li>Hama TS33C, Bresser Thermo/Hygro Sensor -> 14_Hideki</li>
- <li>FreeTec Aussenmodul NC-7344 -> 14_SD_WS07</li>
- </ul>
- <br><br>
- It is possible to attach more than one device in order to get better
- reception, fhem will filter out duplicate messages.<br><br>
- Note: this module require the Device::SerialPort or Win32::SerialPort
- module. It can currently only attatched via USB.
- </td>
- </tr>
- </table>
- <a name="SIGNALduinodefine"></a>
- <b>Define</b><br>
- <code>define <name> SIGNALduino <device> </code> <br>
- <br>
- USB-connected devices (SIGNALduino):<br>
- <ul><li>
- <device> specifies the serial port to communicate with the SIGNALduino.
- The name of the serial-device depends on your distribution, under
- linux the cdc_acm kernel module is responsible, and usually a
- /dev/ttyACM0 or /dev/ttyUSB0 device will be created. If your distribution does not have a
- cdc_acm module, you can force usbserial to handle the SIGNALduino by the
- following command:
- <ul>
- modprobe usbserial
- vendor=0x03eb
- product=0x204b
- </ul>In this case the device is most probably
- /dev/ttyUSB0.<br><br>
- You can also specify a baudrate if the device name contains the @
- character, e.g.: /dev/ttyACM0@57600<br><br>This is also the default baudrate
- It is recommended to specify the device via a name which does not change:
- e.g. via by-id devicename: /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0@57600
- If the baudrate is "directio" (e.g.: /dev/ttyACM0@directio), then the
- perl module Device::SerialPort is not needed, and fhem opens the device
- with simple file io. This might work if the operating system uses sane
- defaults for the serial parameters, e.g. some Linux distributions and
- OSX. <br><br>
- </li>
- </ul>
- <br>
-
- <li><a href="#do_not_notify">do_not_notify</a></li>
- <li><a href="#attrdummy">dummy</a></li>
- <li>debug<br>
- This will bring the module in a very verbose debug output. Usefull to find new signals and verify if the demodulation works correctly.
- </li>
- <li>flashCommand<br>
- This is the command, that is executed to performa the firmware flash. Do not edit, if you don't know what you are doing.<br>
- The default is: avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]<br>
- It contains some place-holders that automatically get filled with the according values:<br>
- <ul>
- <li>[PORT]<br>
- is the port the Signalduino is connectd to (e.g. /dev/ttyUSB0) and will be used from the defenition</li>
- <li>[HEXFILE]<br>
- is the .hex file that shall get flashed. There are three options (applied in this order):<br>
- - passed in set flash<br>
- - taken from the hexFile attribute<br>
- - the default value defined in the module<br>
- </li>
- <li>[LOGFILE]<br>
- The logfile that collects information about the flash process. It gets displayed in FHEM after finishing the flash process</li>
- </ul>
-
- </li>
- <li>hardware<br>
- When using the flash command, you should specify whar hardware you have connected to the usbport. Doing not, can cause failures of the device.
- </li>
- <li>minsecs<br>
- This is a very special attribute. It is provided to other modules. minsecs should act like a threshold. All logic must be done in the logical module.
- If specified, then supported modules will discard new messages if minsecs isn't past.
- </li>
- <li>longids<br>
- Comma separated list of device-types for SIGNALduino that should be handled using long IDs. This additional ID allows it to differentiate some weather sensors, if they are sending on the same channel. Therfor a random generated id is added. If you choose to use longids, then you'll have to define a different device after battery change.<br>
- Default is to not to use long IDs for all devices.
- <br><br>
- Examples:<PRE>
- # Do not use any long IDs for any devices:
- attr sduino longids 0
- # Use any long IDs for all devices (this is default):
- attr sduino longids 1
- # Use longids for BTHR918N devices.
- # Will generate devices names like BTHR918N_f3.
- attr sduino longids BTHR918N
- </PRE></li>
- <li>whitelistIDs<br>
- This attribute allows it, to specify whichs protocos are considured from this module.
- Protocols which are not considured, will not generate logmessages or events. They are then completly ignored.
- This makes it possible to lower ressource usage and give some better clearnes in the logs.
- You can specify multiple whitelistIDs wih a colon : 0,3,7,12<br>
- With a # at the beginnging whitelistIDs can be deactivated.
- </li><br>
- <li>WS09_Model<br>
- WS09_WSModel:undef -> check all, WH1080 -> support WH1080/WS0101 , CTW600 -> support CTW600
- </li>
- <li>WS09_CRCAUS<br>
- WS09_CRCAUS:0,1
- WS09_CRCAUS = 0 is default -> check CRC Calculation for WH1080
- </li><br>
-
- <a name="SIGNALduinoget"></a>
- <b>Get</b>
- <ul>
- <li>version<br>
- return the SIGNALduino firmware version
- </li><br>
- <li>raw<br>
- Issue a SIGNALduino firmware command, and wait for one line of data returned by
- the SIGNALduino. See the SIGNALduino firmware code for details on SIGNALduino
- commands. With this line, you can send almost any signal via a transmitter connected
- </li><br>
- <li>cmds<br>
- Depending on the firmware installed, SIGNALduinos have a different set of
- possible commands. Please refer to the sourcecode of the firmware of your
- SIGNALduino to interpret the response of this command. See also the raw-
- command.
- </li><br>
- <li>ITParms<br>
- For sending IT Signals for wireless switches, the number of repeats and the base duration can be set.
- With the get command, you can verify what is programmed into the uC.
- </li><br>
- <li>protocolIDs<br>
- display a list of the protocol IDs
- </li><br>
- </ul>
- <a name="SIGNALduinoset"></a>
- <b>SET</b>
- <ul>
- <li>ITClock<br>
- Sets the clock which is used to send the signal for IT switches. (Default is 300)
- </li><br>
- <li>raw<br>
- Issue a SIGNALduino firmware command, without waiting data returned by
- the SIGNALduino. See the SIGNALduino firmware code for details on SIGNALduino
- commands. With this line, you can send almost any signal via a transmitter connected
- To send some raw data look at these examples:
- P<protocol id>#binarydata#R<num of repeats>#C<optional clock> (#C is optional)
- <br>Example 1: set sduino raw SR;R=3;P0=500;P1=-9000;P2=-4000;P3=-2000;D=0302030 sends the data in raw mode 3 times repeated
- <br>Example 2: set sduino raw SM;R=3;P0=500;C=250;D=A4F7FDDE sends the data manchester encoded with a clock of 250uS
- <br>Example 3: set sduino raw SC;R=3;SR;P0=5000;SM;P0=500;C=250;D=A4F7FDDE sends a combined message of raw and manchester encoded repeated 3 times
- <br>;
- </p>
- </li><br>
- <li>reset<br>
- This will do a reset of the usb port and normaly causes to reset the uC connected.
- </li><br>
- <li>close<br>
- Closes the connection to the device.
- </li><br>
- <li>flash [hexFile]<br>
- The SIGNALduino needs the right firmware to be able to receive and deliver the sensor data to fhem. In addition to the way using the
- arduino IDE to flash the firmware into the SIGNALduino this provides a way to flash it directly from FHEM.
- There are some requirements:
- <ul>
- <li>avrdude must be installed on the host<br>
- On a Raspberry PI this can be done with: sudo apt-get install avrdude</li>
- <li>the hardware attribute must be set if using any other hardware as an Arduino nano<br>
- This attribute defines the command, that gets sent to avrdude to flash the uC.<br></li>
- <br>
-
- </ul>
- </li>
- <li>sendMsg<br>
- This command will create the needed instructions for sending raw data via the signalduino. Insteaf of specifying the signaldata by your own you specify
- a protocol and the bits you want to send. The command will generate the needed command, that the signalduino will send this.
- <br><br>
- Please note, that this command will work only for MU or MS protocols. You can't transmit manchester data this way.
- <br><br>
- Input args are:
- <p>
- P<protocol id>#binarydata#R<num of repeats>#C<optional clock> (#C is optional)
- <br>Example: P0#0101#R3#C500
- <br>Will generate the raw send command for the message 0101 with protocol 0 and instruct the arduino to send this three times and the clock is 500.
- <br>SR;R=3;P0=500;P1=-9000;P2=-4000;P3=-2000;D=03020302;
- </p>
-
- </li><br>
- <li>enableMessagetype<br>
- Allows you to enable the message processing for
- <ul>
- <li>messages with sync (syncedMS),</li>
- <li>messages without a sync pulse (unsyncedMU) </li>
- <li>manchester encoded messages (manchesterMC) </li>
- </ul>
- The new state will be saved into the eeprom of your arduino.
- </li><br>
- <li>disableMessagetype<br>
- Allows you to disable the message processing for
- <ul>
- <li>messages with sync (syncedMS),</li>
- <li>messages without a sync pulse (unsyncedMU)</li>
- <li>manchester encoded messages (manchesterMC) </li>
- </ul>
- The new state will be saved into the eeprom of your arduino.
- </li>
-
- </ul>
-
-
- =end html
- =cut
|