driq 0.2.0 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: beb5ee5b3d3bdf18dc5f0f228868d99aaa915f72b023d0054c38842730773be3
4
- data.tar.gz: 3d5b872a9d5e94e9ea7ffbb70764b312a484b9f66c3f2e55c9430ca4a80977ba
3
+ metadata.gz: 6b19bed9a7c00d3a975d83d18c05fc0506bda4a10298089bd7649e6e4284ff4a
4
+ data.tar.gz: 88bd1c8cfae747649ee1924bf6bc637b385d8b7f176f69130b2a90a17be08cba
5
5
  SHA512:
6
- metadata.gz: 21f8fcdead5170e9ddae226845bde6af3225fce7776cde26463f57eb45fa3c6ac04e278cbf2d82c2854e827ba3873a892a2a47d3614762f49229e70a59b5f0b8
7
- data.tar.gz: f83aed8ea7c7c7adefa6db38ad976f89f8d08a6e80911fc057adeef3033f5c644701cbd7c052708832359a447e6187303fac6d11c9a2f7b0ff92e10449ff80fd
6
+ metadata.gz: cfe39da41d8d14647b23d506e553b5e429c20bcb2daeba0b1294366554653afaceeda23e7e528c5d6e2cd5068de168bdb96b42c219b77a7fe928488da2967c26
7
+ data.tar.gz: a8d6162074a0e5f4669e24163159a0862a0e4363d2605586b65260239c438277a026992b93f6f0633db4cbcda23f21c49ac128d7ca944b15833fb12d9c4b97dd
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Masatoshi SEKI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/driq.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_development_dependency "test-unit", "~> 3.3"
26
- spec.add_development_dependency "bundler", "~> 1.17"
27
- spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "bundler", ">= 2.2.10"
27
+ spec.add_development_dependency "rake", "~> 12.3.3"
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
29
  end
data/lib/driq.rb CHANGED
@@ -5,10 +5,11 @@ require "json"
5
5
  class Driq
6
6
  include MonitorMixin
7
7
 
8
- def initialize(max_size=100)
8
+ def initialize(size=100)
9
9
  super()
10
10
  @last = 0
11
- @max_size = max_size
11
+ @floor = size
12
+ @ceil = size * 2
12
13
  @list = []
13
14
  @event = new_cond
14
15
  @closed = false
@@ -18,14 +19,15 @@ class Driq
18
19
  synchronize do
19
20
  cell = [make_key, value]
20
21
  @list.push(cell)
22
+ @list = @list.last(@floor) if @list.size > @ceil
21
23
  @event.broadcast
22
24
  return cell.first
23
25
  end
24
26
  end
25
27
  alias push write
26
28
 
27
- def read(key)
28
- readpartial(key, 1).first
29
+ def read(key, timeout=nil)
30
+ readpartial(key, 1, timeout).first
29
31
  end
30
32
 
31
33
  def last(if_empty=nil)
@@ -38,18 +40,18 @@ class Driq
38
40
  @last
39
41
  end
40
42
 
41
- def readpartial(key, size)
43
+ def readpartial(key, size, timeout=nil)
42
44
  synchronize do
43
45
  key = @last unless key
44
46
  raise ClosedQueueError if @closed
45
47
  idx = seek(key)
46
48
  if idx.nil?
47
49
  key = @last
48
- @event.wait
50
+ @event.wait(timeout)
49
51
  idx = seek(key)
50
52
  end
51
53
  raise ClosedQueueError if @closed
52
- @list.slice(idx, size)
54
+ idx ? @list.slice(idx, size) : []
53
55
  end
54
56
  end
55
57
 
@@ -72,12 +74,38 @@ class Driq
72
74
  end
73
75
  end
74
76
 
77
+ class DriqDownstream < Driq
78
+ def initialize(upper, size=100)
79
+ super(size)
80
+ @upper = upper
81
+ Thread.new { download }
82
+ end
83
+
84
+ def write(value)
85
+ @upper.write(value)
86
+ end
87
+
88
+ def download
89
+ while true
90
+ ary = @upper.readpartial(@last, @ceil)
91
+ synchronize do
92
+ @list += ary
93
+ @list = @list.last(@floor) if @list.size > @ceil
94
+ @last = ary.last[0]
95
+ @event.broadcast
96
+ end
97
+ end
98
+ end
99
+ end
100
+
75
101
  class Driq
76
102
  class EventSource
77
- def initialize(driq = nil)
103
+ def initialize(driq = nil, timeout = 60)
78
104
  @driq = driq || Driq.new
105
+ @timeout = timeout
79
106
  end
80
107
  attr_reader :driq
108
+ attr_accessor :timeout
81
109
 
82
110
  def write(value)
83
111
  @driq.write([nil, value])
@@ -111,7 +139,7 @@ class Driq
111
139
  end
112
140
 
113
141
  def read(cursor)
114
- cursor, value = @driq.read(cursor)
142
+ cursor, value = @driq.read(cursor, @timeout) || [cursor, [:ping, 'keep']]
115
143
  return cursor, build_packet(cursor, value[0], value[1])
116
144
  end
117
145
  end
data/lib/driq/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Driq
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.3"
3
3
  end
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+
3
+ cd /home/pi/src/Driq/sample/co2
4
+ /usr/bin/ruby -I ../../../ruby-mh-z19/lib co2.rb
@@ -0,0 +1,125 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>CO2</title>
5
+ </head>
6
+ <style type="text/css" media="screen">
7
+ body {
8
+ font-family: Helvetica;
9
+ background: #FFFFFF;
10
+ color: #000000; 
11
+ }
12
+
13
+ #myChart {
14
+ position: relative;
15
+ height:300; width:150
16
+ }
17
+ </style>
18
+ <body>
19
+ <div class="head">
20
+ <h2>CO2 <span id="co2"></span></h2>
21
+ </div>
22
+ <div class="main">
23
+ <canvas id="myChart" style="position: relative; height:100; width:150"></canvas>
24
+ </div>
25
+
26
+ </body>
27
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
28
+ <script>
29
+
30
+ var evt = new EventSource('stream');
31
+
32
+ evt.onmessage = function(e) {
33
+ var it = JSON.parse(e.data);
34
+ console.log(it);
35
+ console.log(new Date(Number(e.lastEventId) * 0.001));
36
+ time = new Date(Number(e.lastEventId) * 0.001);
37
+ add_data(it['concentration'], it['temperature'], time);
38
+ };
39
+
40
+ var co2_text = document.getElementById("co2");
41
+
42
+ function add_data(concentration, temperature, time) {
43
+ chartDataSet.data.datasets[0].data.push({
44
+ y: concentration,
45
+ t: time
46
+ });
47
+ chartDataSet.data.datasets[1].data.push({
48
+ y: temperature,
49
+ t: time
50
+ });
51
+ while (time - chartDataSet.data.datasets[0].data[0].t > 3600000) {
52
+ chartDataSet.data.datasets[0].data.shift();
53
+ chartDataSet.data.datasets[1].data.shift();
54
+ }
55
+ chart.update();
56
+ co2_text.textContent = concentration + 'ppm';
57
+ document.title = concentration + 'ppm';
58
+ }
59
+
60
+ var ctx = document.getElementById("myChart").getContext('2d');
61
+ const chartDataSet = {
62
+ type: 'line',
63
+ responsive: false,
64
+ aspectRatio: 2,
65
+ data: {
66
+ datasets: [{
67
+ label: 'ppm',
68
+ data: [],
69
+ borderColor: "rgb(54, 162, 235)",
70
+ fill: false,
71
+ yAxisID: "y-axis-1"
72
+ }, {
73
+ label: 'temp',
74
+ data: [],
75
+ borderColor: "rgb(235, 0, 0)",
76
+ fill: false,
77
+ yAxisID: "y-axis-2"
78
+ }]
79
+ },
80
+ options: {
81
+ scales: {
82
+ xAxes: [{
83
+ type: 'time',
84
+ time: {
85
+ displayFormats: {
86
+ millisecond: 'h:mm',
87
+ second: 'h:mm',
88
+ minute: 'h:mm'
89
+ },
90
+ unit: 'minute'
91
+ },
92
+ distribution: 'linear',
93
+ ticks: {
94
+ maxTicksLimit:6,
95
+ source: 'data'
96
+ },
97
+ gridLines: {
98
+ display: false
99
+ }
100
+ }],
101
+ yAxes: [{
102
+ id: 'y-axis-1',
103
+ ticks: {
104
+ source: 'data',
105
+ min: 200,
106
+ max: 2000
107
+ }
108
+ }, {
109
+ id: 'y-axis-2',
110
+ position: 'right',
111
+ ticks: {
112
+ source: 'data',
113
+ min: -5,
114
+ max: 40
115
+ },
116
+ gridLines: {
117
+ display: false
118
+ }
119
+ }]
120
+ }
121
+ }
122
+ };
123
+ var chart = new Chart(ctx, chartDataSet);
124
+ </script>
125
+ </html>
data/sample/co2/co2.rb ADDED
@@ -0,0 +1,60 @@
1
+ require 'webrick'
2
+ require 'driq'
3
+ require 'driq/webrick'
4
+ require 'mh-z19'
5
+
6
+ class CO2
7
+ def initialize(port)
8
+ @src = Driq::EventSource.new
9
+ @svr = WEBrick::HTTPServer.new(:Port => port)
10
+
11
+ @svr.mount_proc('/') do |req, res|
12
+ on_index(req, res)
13
+ end
14
+
15
+ @svr.mount_proc('/stream') do |req, res|
16
+ on_stream(req, res)
17
+ end
18
+
19
+ @front = {"src" => @src,
20
+ "webrick" => @svr,
21
+ "body" => File.read('co2.html')}
22
+ end
23
+
24
+ def on_index(req, res)
25
+ res.body = File.read("co2.html")
26
+ end
27
+
28
+ def on_stream(req, res)
29
+ last_event_id = req["Last-Event-ID"] || 0
30
+ res.content_type = 'text/event-stream'
31
+ res.chunked = true
32
+ res.body = WEBrick::ChunkedStream.new(Driq::EventStream.new(@src, last_event_id))
33
+ end
34
+
35
+ def start
36
+ Thread.new { co2_loop }
37
+ @svr.start
38
+ end
39
+
40
+ def co2_loop
41
+ co2 = MH_Z19::Serial.new('/dev/serial0')
42
+ last = nil
43
+ sleep 3
44
+ loop do
45
+ begin
46
+ detail = co2.read_concentration_detail rescue nil
47
+ @src.write(detail) unless last == detail
48
+ last = detail
49
+ rescue MH_Z19::Serial::InvalidPacketException
50
+ p $!
51
+ end
52
+ sleep 60
53
+ end
54
+ end
55
+ end
56
+
57
+ port = Integer(ENV['PORT']) rescue 8080
58
+
59
+ co2 = CO2.new(port)
60
+ co2.start
@@ -0,0 +1,16 @@
1
+ #
2
+
3
+ [Unit]
4
+ Description=MH-Z14A CO2 Server
5
+ After=network.target
6
+ After=syslog.target
7
+
8
+ [Install]
9
+ WantedBy=multi-user.target
10
+
11
+ [Service]
12
+ User=pi
13
+ Group=pi
14
+ Type=simple
15
+ ExecStart=/home/pi/src/Driq/sample/co2/co2-service.sh
16
+ Restart=always
@@ -0,0 +1,85 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Koto</title>
5
+ </head>
6
+ <style type="text/css" media="screen">
7
+ body {
8
+ font-family: Helvetica;
9
+ background: #FFFFFF;
10
+ color: #000000; 
11
+ }
12
+
13
+ .EnterTofu input {
14
+ box-sizing: border-box;
15
+ width: 100%;
16
+ padding: 16px 6px 6px 6px;
17
+ font-size: 16px;
18
+ font-weight: normal;
19
+ background: #6d84a2;
20
+ }
21
+
22
+ .ListTofu > ul {
23
+ margin: 0;
24
+ padding: 0;
25
+ }
26
+
27
+ .ListTofu > ul > li {
28
+ border-bottom: 1px solid #E0E0E0;
29
+ padding: 8px 0 8px 10px;
30
+ font-size: 14px;
31
+ font-weight: bold;
32
+ list-style: none:
33
+ }
34
+
35
+ .ListTofu > ul > li.group {
36
+ top: -1px;
37
+ margin-bottom: -2px;
38
+ border-top: 1px solid #7d7d7d;
39
+ border-bottom: 1px solid #999999;
40
+ padding: 1px 5px;
41
+ font-size: 13px;
42
+ font-weight: bold;
43
+ text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
44
+ color: #FFFFFF;
45
+ }
46
+ </style>
47
+ <body>
48
+ <div class="EnterTofu">
49
+ <input id='enter' type='text' size='40' name='str' value='' autocomplete='off' autofocus onchange="postNews();"/>
50
+ </div>
51
+ <div class="ListTofu">
52
+ <ul id="list">
53
+ </ul>
54
+ </div>
55
+ </body>
56
+ <script>
57
+ var evt = new EventSource('stream');
58
+ var input = document.querySelector("#enter");
59
+ var eventList = document.getElementById('list');
60
+
61
+ evt.onmessage = function(e) {
62
+ var entry = JSON.parse(e.data);
63
+
64
+ var newString = document.createElement("li");
65
+ newString.textContent = entry["text"];
66
+
67
+ var newGroup = document.createElement("li");
68
+ newGroup.textContent = entry["group"];
69
+ newGroup.classList.add("group");
70
+ newGroup.style.color = entry["color"];
71
+
72
+ eventList.prepend(newGroup, newString);
73
+
74
+ document.title = entry["text"];
75
+ };
76
+
77
+ function postNews() {
78
+ var xhr = new XMLHttpRequest();
79
+ xhr.open("POST", "news");
80
+ xhr.setRequestHeader("Content-Type", "application/json");
81
+ xhr.send(JSON.stringify({"text": input.value}));
82
+ input.value = "";
83
+ }
84
+ </script>
85
+ </html>
@@ -0,0 +1,74 @@
1
+ require 'webrick'
2
+ require 'driq'
3
+ require 'driq/webrick'
4
+ require 'drb'
5
+ require 'digest/md5'
6
+
7
+ class Koto
8
+ def initialize(port, drb_url)
9
+ @src = Driq::EventSource.new
10
+ @svr = WEBrick::HTTPServer.new(:Port => port)
11
+
12
+ @svr.mount_proc('/') do |req, res|
13
+ on_index(req, res)
14
+ end
15
+
16
+ @svr.mount_proc('/stream') do |req, res|
17
+ on_stream(req, res)
18
+ end
19
+
20
+ @svr.mount_proc('/news') do |req, res|
21
+ on_news(req, res)
22
+ end
23
+
24
+ @front = {"src" => @src,
25
+ "webrick" => @svr,
26
+ "body" => File.read('koto.html')}
27
+ DRb.start_service(drb_url, @front)
28
+ end
29
+
30
+ def on_index(req, res)
31
+ res.body = @front["body"]
32
+ end
33
+
34
+ def on_stream(req, res)
35
+ last_event_id = req["Last-Event-ID"] || 0
36
+ res.content_type = 'text/event-stream'
37
+ res.chunked = true
38
+ res.body = WEBrick::ChunkedStream.new(Driq::EventStream.new(@src, last_event_id))
39
+ end
40
+
41
+ def on_news(req, res)
42
+ it = make_entry(req)
43
+ @src.write(it)
44
+ res.content_type = "text/plain"
45
+ res.body = "i know";
46
+ end
47
+
48
+ Color = Hash.new do |h, k|
49
+ md5 = Digest::MD5.new
50
+ md5 << k.to_s
51
+ r = 0b01111111 & md5.digest[0].unpack("c").first
52
+ g = 0b01111111 & md5.digest[1].unpack("c").first
53
+ b = 0b01111111 & md5.digest[2].unpack("c").first
54
+ h[k] = sprintf("#%02x%02x%02x", r, g, b)
55
+ end
56
+
57
+ def make_entry(req)
58
+ text = JSON.parse(req.body)["text"] || ""
59
+ from = req["X-Forwarded-For"] || req.peeraddr[2]
60
+ color = Color[from]
61
+ group = [from, Time.now.strftime("%H:%M")].join(" @ ")
62
+ {"text" => text, "group" => group, "color" => color}
63
+ end
64
+
65
+ def start
66
+ @svr.start
67
+ end
68
+ end
69
+
70
+ port = Integer(ENV['TOFU_PORT']) rescue 10510
71
+ drb_url = 'druby://localhost:55443'
72
+
73
+ koto = Koto.new(port, drb_url)
74
+ koto.start
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: driq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masatoshi SEKI
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-03 00:00:00.000000000 Z
11
+ date: 2021-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -28,30 +28,30 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.17'
33
+ version: 2.2.10
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.17'
40
+ version: 2.2.10
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: 12.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: 12.3.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -75,12 +75,19 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
77
  - Gemfile
78
+ - LICENSE
78
79
  - README.md
79
80
  - Rakefile
80
81
  - driq.gemspec
81
82
  - lib/driq.rb
82
83
  - lib/driq/version.rb
83
84
  - lib/driq/webrick.rb
85
+ - sample/co2/co2-service.sh
86
+ - sample/co2/co2.html
87
+ - sample/co2/co2.rb
88
+ - sample/co2/co2.service
89
+ - sample/koto/koto.html
90
+ - sample/koto/koto.rb
84
91
  homepage: https://github.com/seki/Driq
85
92
  licenses: []
86
93
  metadata: {}
@@ -99,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
106
  - !ruby/object:Gem::Version
100
107
  version: '0'
101
108
  requirements: []
102
- rubygems_version: 3.1.2
109
+ rubygems_version: 3.2.3
103
110
  signing_key:
104
111
  specification_version: 4
105
112
  summary: simple rd-stream