create_sensor_db.sql 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. CREATE DATABASE if not exists tsensor;
  2. create user if not exists 'sensor'@'localhost' identified by 'Whillmqq';
  3. create user if not exists 'sensordataread'@'localhost' identified by 'Whill';
  4. create table if not exists tsensor.datain (timestamp bigint unsigned not null comment 'Zeitstempel der Sensordaten',
  5. topic varchar(256) comment 'topic, unter den dieses Datum verwaltet wird',
  6. value bigint not null comment 'Sensordaten als Integer');
  7. create table if not exists tsensor.data_storage (timestamp bigint unsigned not null comment 'Zeitstempel der Sensordaten als epoch',
  8. topicid int unsigned not null comment 'numerische ID des Topics aus der Topic-Tabelle',
  9. value bigint not null comment 'Sensordaten als Integer', index (timestamp,topicid));
  10. create table if not exists tsensor.data_retent as select * from tsensor.data_storage;
  11. create table if not exists tsensor.last_data (topicid int unsigned not null comment 'numerische ID des Topics aus der Topic-Tabelle',
  12. value bigint not null comment 'Sensordaten als Integer', index (topicid));
  13. create table if not exists tsensor.cfg_topic (feld varchar(256) comment 'Bezeichnung des topic-Anteils',
  14. pos tinyint not null comment 'Position innerhalb des Topics',
  15. minlength tinyint comment 'Mindestanzahl an elementen, die das Topic haben muss, damit die Regel greift');
  16. create table if not exists tsensor.topic_list (topicid int unsigned not null primary key comment 'numerische ID des topics',
  17. topic varchar(256) not null unique comment 'Topic');
  18. create table if not exists tsensor.topic_def (topicid int unsigned not null comment 'Interne ID eines topics',
  19. feld varchar(256) comment 'Bezeichnung des Datums',
  20. inhalt varchar(256) comment 'Inhalt des Datums',index (topicid,feld));
  21. create or replace view tsensor.data_view as select utd.*,tl.topic,tdq.inhalt as quantity,tdd.inhalt as device,tdi.inhalt as internal_id from ((select ds.timestamp/1000 as time,ds.topicid,ds.value from tsensor.data_storage ds) union (select ds.timestamp/1000 as time,ds.topicid,ds.value from tsensor.data_retent ds)) utd
  22. join tsensor.topic_list tl on utd.topicid=tl.topicid
  23. left join tsensor.topic_def tdq on tdq.topicid=utd.topicid and tdq.feld='quantity'
  24. left join tsensor.topic_def tdd on tdd.topicid=utd.topicid and tdq.feld='device'
  25. left join tsensor.topic_def tdi on tdi.topicid=utd.topicid and tdq.feld='internal_id';
  26. grant select,insert,update on tsensor.data_storage to 'sensor'@'localhost' with grant option;
  27. grant insert,select,update on tsensor.last_data to 'sensor'@'localhost' with grant option;
  28. grant insert,select on tsensor.topic_list to 'sensor'@'localhost' with grant option;
  29. grant insert,select on tsensor.topic_def to 'sensor'@'localhost' with grant option;
  30. grant execute on tsensor.* to 'sensor'@'localhost' with grant option;
  31. grant select on tsensor.data_storage to 'sensordataread'@'localhost' with grant option;
  32. grant select on tsensor.data_view to 'sensordataread'@'localhost' with grant option;
  33. delimiter //
  34. create or replace procedure tsensor.retent_data()
  35. begin
  36. declare tid bigint;
  37. declare btopicdone int;
  38. declare topic_curs cursor for select distinct topic_list.topicid from topic_list;
  39. declare continue handler for not found set btopicdone = 1;
  40. open topic_curs;
  41. repeat
  42. fetch topic_curs into tid;
  43. select count(*) into @actcount from data_storage where topicid=tid;
  44. if (@actcount > 2) then
  45. select min(timestamp) into @mts from (select timestamp from data_storage where topicid=tid order by timestamp desc limit 2) td ;
  46. insert into data_retent select * from data_storage where topicid=tid and timestamp < @mts;
  47. delete from data_storage where topicid=tid and timestamp < @mts;
  48. commit;
  49. end if;
  50. until btopicdone end repeat;
  51. close topic_curs;
  52. end
  53. //
  54. delimiter ;
  55. DELIMITER //
  56. CREATE OR REPLACE PROCEDURE tsensor.insert_topic(vtopic varchar(1024),newid int unsigned)
  57. begin
  58. declare tpos tinyint;
  59. declare feldname varchar(1024);
  60. DECLARE bcfgDone INT;
  61. DECLARE cfg_curs CURSOR FOR SELECT cfg_topic.feld,cfg_topic.pos FROM cfg_topic where cfg_topic.minlength is null or cfg_topic.minlength <= (select (length(vtopic) - length(replace(vtopic,'/','')) +1));
  62. DECLARE CONTINUE HANDLER FOR NOT FOUND SET bcfgDone = 1;
  63. OPEN cfg_curs;
  64. REPEAT
  65. fetch cfg_curs into feldname,tpos;
  66. if (tpos < 0) then
  67. select substring_index(substring_index(vtopic,'/',tpos),'/',1) into @feldinhalt;
  68. else
  69. select substring_index(substring_index(vtopic,'/',tpos),'/',-1) into @feldinhalt;
  70. end if;
  71. if (select count(*) from topic_def where topic_def.topicid = newid and topic_def.feld=feldname) = 0 then
  72. insert into topic_def (topicid,feld,inhalt) values (newid,feldname,@feldinhalt);
  73. commit;
  74. end if;
  75. UNTIL bcfgDone END REPEAT;
  76. close cfg_curs;
  77. end
  78. //
  79. DELIMITER ;
  80. DELIMITER //
  81. CREATE OR REPLACE PROCEDURE tsensor.insert_data(IN intopic varchar(256),IN invalue bigint,IN tstamp bigint unsigned)
  82. BEGIN
  83. select crc32(intopic) into @crctopic;
  84. if (@crctopic is null) then
  85. signal sqlstate '45000' set mysql_errno=32100,message_text='Missing topic';
  86. end if;
  87. if (select invalue is null) then
  88. signal sqlstate '45000' set mysql_errno=32100,message_text='Missing value';
  89. end if;
  90. if (select tstamp is null) then
  91. signal sqlstate '45000' set mysql_errno=32100,message_text='Missing timestamp';
  92. end if;
  93. if (@crctopic in (select topicid from topic_list))=0 then
  94. # new topic means no value existent
  95. call insert_topic(intopic,@crctopic);
  96. insert into topic_list (topicid,topic) values (@crctopic,intopic);
  97. insert into data_storage (timestamp,topicid,value) values (tstamp,@crctopic,invalue);
  98. insert into last_data (topicid,value) values (@crctopic,invalue);
  99. else
  100. # topic exists and values should be available
  101. if (invalue not in (select value from last_data where topicid=@crctopic)) then
  102. insert into data_storage (timestamp,topicid,value) values (tstamp,@crctopic,invalue);
  103. update last_data set value=invalue where topicid=@crctopic;
  104. else
  105. if (select count(distinct td.value) from (select data_storage.value from data_storage where topicid=@crctopic and (data_storage.timestamp > (unix_timestamp(now())-300)*1000) order by timestamp desc limit 2) td) = 1 then
  106. update data_storage set timestamp=tstamp where topicid=@crctopic and timestamp=(select max(timestamp) from data_storage where topicid=@crctopic);
  107. else
  108. insert into data_storage (timestamp,topicid,value) values (tstamp,@crctopic,invalue);
  109. end if; # check if second last match
  110. end if; # compare with last value
  111. end if; # topicid is null
  112. commit;
  113. END
  114. //
  115. DELIMITER ;
  116. grant execute on tsensor.* to 'sensor'@'localhost' with grant option;
  117. set global event_scheduler=ON;
  118. create event if not exists tsensor.retent_old_data on schedule every 1 hour do call tsensor.retent_data();
  119. insert into tsensor.cfg_topic (feld,pos,minlength) values ('device',2,NULL);
  120. insert into tsensor.cfg_topic (feld,pos,minlength) values ('quantity',-1,NULL);
  121. insert into tsensor.cfg_topic (feld,pos,minlength) values ('place',3,NULL);
  122. insert into tsensor.cfg_topic (feld,pos,minlength) values ('internal_id',4,5);
  123. commit;