dredger-iot 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/dredger +31 -11
- data/lib/dredger/iot/bus/gpio.rb +4 -0
- data/lib/dredger/iot/bus/gpio_label_adapter.rb +4 -0
- data/lib/dredger/iot/bus/i2c.rb +4 -0
- data/lib/dredger/iot/pins/beaglebone.rb +1 -7
- data/lib/dredger/iot/pins/raspberry_pi.rb +1 -5
- data/lib/dredger/iot/pins.rb +12 -0
- data/lib/dredger/iot/sensors/adxl345.rb +1 -1
- data/lib/dredger/iot/sensors/adxl345_provider.rb +5 -1
- data/lib/dredger/iot/sensors/dht22_provider.rb +3 -8
- data/lib/dredger/iot/sensors/ds18b20_provider.rb +6 -0
- data/lib/dredger/iot/sensors/neo6m.rb +1 -1
- data/lib/dredger/iot/sensors/neo6m_provider.rb +3 -3
- data/lib/dredger/iot/sensors/scd30.rb +1 -1
- data/lib/dredger/iot/sensors/scd30_provider.rb +2 -2
- data/lib/dredger/iot/sensors/yf_s201_provider.rb +4 -6
- data/lib/dredger/iot/version.rb +1 -1
- metadata +11 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20a13d73758a754dfef92919adab2c1bd3f7a22de71e523ebb5601ecd292d97f
|
|
4
|
+
data.tar.gz: 32d57b97d774f40cec842d1ef99b90c134687c6b7d418e60587dcfa77d8bd17b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fdfd0dde86a514d2ffd829d9e74f4c834c7e8784257114f80a66321a6bc8b1e7d3329998197b6deabd5a31a19ee227eb28c56f9c28a84b8835e63b721e7ec082
|
|
7
|
+
data.tar.gz: 4921e4d495ee0d6d7b06f4f69912f2e80e1c5711b43af5eb8259d2331b46b0f036ad1cb89d23613d5b7857af4b612a2494bf09a38cdd0411b5423a95cb81fbec
|
data/bin/dredger
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require 'bundler/setup'
|
|
5
4
|
require 'dredger/iot'
|
|
6
5
|
require 'optparse'
|
|
7
6
|
require 'json'
|
|
@@ -90,15 +89,17 @@ class DredgerCLI
|
|
|
90
89
|
|
|
91
90
|
def list_sensors
|
|
92
91
|
sensors = {
|
|
93
|
-
'dht22' => 'DHT22 - Temperature/Humidity (GPIO)',
|
|
92
|
+
'dht22' => 'DHT22 - Temperature/Humidity (GPIO) [requires C extension]',
|
|
94
93
|
'bme280' => 'BME280 - Temperature/Humidity/Pressure (I2C)',
|
|
95
94
|
'ds18b20' => 'DS18B20 - Waterproof Temperature (1-Wire)',
|
|
96
|
-
'bmp180' => 'BMP180 - Barometric Pressure/Temperature (I2C)',
|
|
97
|
-
'mcp9808' => 'MCP9808 - High-Accuracy Temperature (I2C)',
|
|
98
95
|
'sht31' => 'SHT31 - Temperature/Humidity (I2C)',
|
|
99
96
|
'bh1750' => 'BH1750 - Ambient Light (I2C)',
|
|
100
97
|
'tsl2561' => 'TSL2561 - Ambient Light (I2C)',
|
|
101
|
-
'ina219' => 'INA219 - Bus Voltage/Current (I2C)'
|
|
98
|
+
'ina219' => 'INA219 - Bus Voltage/Current (I2C)',
|
|
99
|
+
'adxl345' => 'ADXL345 - 3-Axis Accelerometer (I2C)',
|
|
100
|
+
'scd30' => 'SCD30 - CO2/Temperature/Humidity (I2C)',
|
|
101
|
+
'yf_s201' => 'YF-S201 - Water Flow Meter (GPIO)',
|
|
102
|
+
'neo6m' => 'NEO-6M - GPS Module (UART/Serial)'
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
puts 'Available Sensors:'
|
|
@@ -168,6 +169,25 @@ class DredgerCLI
|
|
|
168
169
|
shunt = @options[:ina219_shunt] || 0.1
|
|
169
170
|
provider = Dredger::IoT::Sensors::INA219Provider.new(i2c_bus: i2c, shunt_resistance_ohms: shunt)
|
|
170
171
|
Dredger::IoT::Sensors::INA219.new(i2c_addr: addr, provider: provider)
|
|
172
|
+
when 'adxl345'
|
|
173
|
+
addr = (args.shift || '0x53').to_i(16)
|
|
174
|
+
i2c = Dredger::IoT::Bus::Auto.i2c
|
|
175
|
+
provider = Dredger::IoT::Sensors::ADXL345Provider.new(i2c_bus: i2c)
|
|
176
|
+
Dredger::IoT::Sensors::ADXL345.new(i2c_addr: addr, provider: provider)
|
|
177
|
+
when 'scd30'
|
|
178
|
+
addr = (args.shift || '0x61').to_i(16)
|
|
179
|
+
i2c = Dredger::IoT::Bus::Auto.i2c
|
|
180
|
+
provider = Dredger::IoT::Sensors::SCD30Provider.new(i2c_bus: i2c)
|
|
181
|
+
Dredger::IoT::Sensors::SCD30.new(i2c_addr: addr, provider: provider)
|
|
182
|
+
when 'yf_s201'
|
|
183
|
+
pin = args.shift || 'P9_12'
|
|
184
|
+
gpio = Dredger::IoT::Bus::Auto.gpio
|
|
185
|
+
provider = Dredger::IoT::Sensors::YFS201Provider.new(gpio_bus: gpio)
|
|
186
|
+
Dredger::IoT::Sensors::YFS201.new(pin_label: pin, provider: provider)
|
|
187
|
+
when 'neo6m'
|
|
188
|
+
device = args.shift || '/dev/ttyAMA0'
|
|
189
|
+
provider = Dredger::IoT::Sensors::NEO6MProvider.new
|
|
190
|
+
Dredger::IoT::Sensors::NEO6M.new(device: device, provider: provider)
|
|
171
191
|
else
|
|
172
192
|
puts "Error: Unknown sensor type '#{type}'"
|
|
173
193
|
exit 1
|
|
@@ -201,7 +221,7 @@ class DredgerCLI
|
|
|
201
221
|
sensor_type: r.sensor_type,
|
|
202
222
|
value: r.value,
|
|
203
223
|
unit: r.unit,
|
|
204
|
-
timestamp: r.
|
|
224
|
+
timestamp: r.recorded_at.iso8601
|
|
205
225
|
}
|
|
206
226
|
end
|
|
207
227
|
puts JSON.pretty_generate(data)
|
|
@@ -289,11 +309,11 @@ class DredgerCLI
|
|
|
289
309
|
|
|
290
310
|
puts
|
|
291
311
|
puts 'Recommendations:'
|
|
292
|
-
puts
|
|
293
|
-
puts
|
|
294
|
-
puts
|
|
295
|
-
puts
|
|
296
|
-
puts
|
|
312
|
+
puts ' sudo apt-get install gpiod i2c-tools'
|
|
313
|
+
puts ' sudo usermod -a -G gpio $USER # for GPIO access'
|
|
314
|
+
puts ' sudo usermod -a -G i2c $USER # for I2C access'
|
|
315
|
+
puts ' sudo modprobe i2c-dev'
|
|
316
|
+
puts ' sudo modprobe w1-gpio; sudo modprobe w1-therm'
|
|
297
317
|
end
|
|
298
318
|
|
|
299
319
|
def check_device_node(path, desc)
|
data/lib/dredger/iot/bus/gpio.rb
CHANGED
data/lib/dredger/iot/bus/i2c.rb
CHANGED
|
@@ -5,13 +5,7 @@ module Dredger
|
|
|
5
5
|
module Pins
|
|
6
6
|
# Beaglebone header label mapping placeholder.
|
|
7
7
|
class Beaglebone
|
|
8
|
-
|
|
9
|
-
# Chip:line resolution is done at runtime by the agent or a backend.
|
|
10
|
-
PinRef = Struct.new(:label, :chip, :line, keyword_init: true) do
|
|
11
|
-
def to_s
|
|
12
|
-
chip && line ? "#{label}(chip#{chip}:#{line})" : label.to_s
|
|
13
|
-
end
|
|
14
|
-
end
|
|
8
|
+
PinRef = Pins::PinRef
|
|
15
9
|
|
|
16
10
|
KNOWN_LABELS = (
|
|
17
11
|
(0..46).map { |n| "P8_#{n}" } + (0..46).map { |n| "P9_#{n}" }
|
|
@@ -8,11 +8,7 @@ module Dredger
|
|
|
8
8
|
# - GPIO17, BCM17
|
|
9
9
|
# - PIN11 (a.k.a. BOARD11)
|
|
10
10
|
class RaspberryPi
|
|
11
|
-
PinRef =
|
|
12
|
-
def to_s
|
|
13
|
-
chip && line ? "#{label}(chip#{chip}:#{line})" : label.to_s
|
|
14
|
-
end
|
|
15
|
-
end
|
|
11
|
+
PinRef = Pins::PinRef
|
|
16
12
|
|
|
17
13
|
# Subset of BOARD pin to BCM mapping for common usable GPIOs on 40-pin header
|
|
18
14
|
BOARD_TO_BCM = {
|
data/lib/dredger/iot/pins.rb
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Dredger
|
|
4
|
+
module IoT
|
|
5
|
+
module Pins
|
|
6
|
+
PinRef = Struct.new(:label, :chip, :line, keyword_init: true) do
|
|
7
|
+
def to_s
|
|
8
|
+
chip && line ? "#{label}(chip#{chip}:#{line})" : label.to_s
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
3
15
|
require_relative 'pins/beaglebone'
|
|
4
16
|
require_relative 'pins/raspberry_pi'
|
|
@@ -8,7 +8,7 @@ module Dredger
|
|
|
8
8
|
# Uses a provider interface to allow simulation in tests and hardware backends in production.
|
|
9
9
|
class ADXL345 < BaseSensor
|
|
10
10
|
# provider must respond to :read_measurements(i2c_addr) -> { x_g:, y_g:, z_g: }
|
|
11
|
-
def initialize(i2c_addr: 0x53,
|
|
11
|
+
def initialize(provider:, i2c_addr: 0x53, metadata: {})
|
|
12
12
|
super(metadata: metadata)
|
|
13
13
|
@i2c_addr = i2c_addr
|
|
14
14
|
@provider = provider
|
|
@@ -33,6 +33,7 @@ module Dredger
|
|
|
33
33
|
@i2c = i2c_bus
|
|
34
34
|
@range = range
|
|
35
35
|
@scale_factor = calculate_scale_factor(range)
|
|
36
|
+
@configured = false
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# Read acceleration measurements from the ADXL345 at the given I2C address.
|
|
@@ -43,7 +44,10 @@ module Dredger
|
|
|
43
44
|
raise IOError, "ADXL345 not found (devid=0x#{dev_id.to_s(16)})" unless dev_id == DEVID_EXPECTED
|
|
44
45
|
|
|
45
46
|
# Configure sensor (one-time setup)
|
|
46
|
-
|
|
47
|
+
unless @configured
|
|
48
|
+
configure_sensor(addr)
|
|
49
|
+
@configured = true
|
|
50
|
+
end
|
|
47
51
|
|
|
48
52
|
# Read 6 bytes of acceleration data (X, Y, Z as 16-bit signed integers)
|
|
49
53
|
raw = @i2c.read(addr, 6, register: DATAX0_REG)
|
|
@@ -64,14 +64,9 @@ module Dredger
|
|
|
64
64
|
# This is a stub - real implementation requires precise timing.
|
|
65
65
|
# In production, consider using a kernel driver or hardware peripheral.
|
|
66
66
|
def read_40_bits(_pin_label)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
# If high > 40us, bit=1; else bit=0
|
|
71
|
-
warn 'DHT22Provider: bit-banging not fully implemented, returning stub data'
|
|
72
|
-
# humidity=65.2% => 0x028C, temp=31.4°C => 0x013A
|
|
73
|
-
# checksum = (0x02 + 0x8C + 0x01 + 0x3A) & 0xFF = 0xC9
|
|
74
|
-
[0x02, 0x8C, 0x01, 0x3A, 0xC9]
|
|
67
|
+
raise NotImplementedError,
|
|
68
|
+
'DHT22 bit-banging requires microsecond timing not achievable in pure Ruby. ' \
|
|
69
|
+
'Use a C extension, kernel driver (e.g., dht11 kernel module), or hardware peripheral.'
|
|
75
70
|
end
|
|
76
71
|
end
|
|
77
72
|
end
|
|
@@ -23,7 +23,13 @@ module Dredger
|
|
|
23
23
|
# Read temperature from DS18B20 sensor.
|
|
24
24
|
# device_id: device address (e.g., "28-0000056789ab")
|
|
25
25
|
# Returns temperature in Celsius as Float
|
|
26
|
+
VALID_DEVICE_ID = /\A28-[0-9a-f]+\z/
|
|
27
|
+
|
|
26
28
|
def read_temperature(device_id)
|
|
29
|
+
unless device_id.match?(VALID_DEVICE_ID)
|
|
30
|
+
raise ArgumentError, "Invalid DS18B20 device_id: #{device_id}. Expected format: 28-xxxxxxxxxxxx"
|
|
31
|
+
end
|
|
32
|
+
|
|
27
33
|
device_path = File.join(@base_path, device_id, 'w1_slave')
|
|
28
34
|
raise IOError, "DS18B20 device not found: #{device_id}" unless File.exist?(device_path)
|
|
29
35
|
|
|
@@ -8,7 +8,7 @@ module Dredger
|
|
|
8
8
|
# Uses a provider interface to allow simulation in tests and hardware backends in production.
|
|
9
9
|
class NEO6M < BaseSensor
|
|
10
10
|
# provider must respond to :read_position(device) -> { latitude:, longitude:, altitude:, speed:, satellites: }
|
|
11
|
-
def initialize(device: '/dev/ttyAMA0',
|
|
11
|
+
def initialize(provider:, device: '/dev/ttyAMA0', metadata: {})
|
|
12
12
|
super(metadata: metadata)
|
|
13
13
|
@device = device
|
|
14
14
|
@provider = provider
|
|
@@ -45,9 +45,9 @@ module Dredger
|
|
|
45
45
|
line = read_line(serial, @timeout)
|
|
46
46
|
next unless line
|
|
47
47
|
|
|
48
|
-
if line.start_with?('$GPGGA'
|
|
48
|
+
if line.start_with?('$GPGGA', '$GNGGA')
|
|
49
49
|
gga_data = parse_gga(line)
|
|
50
|
-
elsif line.start_with?('$GPRMC'
|
|
50
|
+
elsif line.start_with?('$GPRMC', '$GNRMC')
|
|
51
51
|
rmc_data = parse_rmc(line)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -125,7 +125,7 @@ module Dredger
|
|
|
125
125
|
degree_digits = coord_str.length >= 5 && coord_str[4] == '.' ? 2 : 3
|
|
126
126
|
|
|
127
127
|
degrees = coord_str[0, degree_digits].to_f
|
|
128
|
-
minutes = coord_str[degree_digits
|
|
128
|
+
minutes = coord_str[degree_digits..].to_f
|
|
129
129
|
|
|
130
130
|
decimal_degrees = degrees + (minutes / 60.0)
|
|
131
131
|
|
|
@@ -8,7 +8,7 @@ module Dredger
|
|
|
8
8
|
# Uses a provider interface to allow simulation in tests and hardware backends in production.
|
|
9
9
|
class SCD30 < BaseSensor
|
|
10
10
|
# provider must respond to :read_measurements(i2c_addr) -> { co2_ppm:, temperature_c:, humidity: }
|
|
11
|
-
def initialize(i2c_addr: 0x61,
|
|
11
|
+
def initialize(provider:, i2c_addr: 0x61, metadata: {})
|
|
12
12
|
super(metadata: metadata)
|
|
13
13
|
@i2c_addr = i2c_addr
|
|
14
14
|
@provider = provider
|
|
@@ -87,7 +87,7 @@ module Dredger
|
|
|
87
87
|
sleep(0.01)
|
|
88
88
|
status = @i2c.read(addr, 3)
|
|
89
89
|
# Data ready when bit 0 of word is 1
|
|
90
|
-
data_ready =
|
|
90
|
+
data_ready = status[1].allbits?(0x01)
|
|
91
91
|
return if data_ready
|
|
92
92
|
|
|
93
93
|
raise IOError, 'SCD30 data ready timeout' if Time.now - start_time > timeout
|
|
@@ -130,7 +130,7 @@ module Dredger
|
|
|
130
130
|
data.each do |byte|
|
|
131
131
|
crc ^= byte
|
|
132
132
|
8.times do
|
|
133
|
-
crc = (
|
|
133
|
+
crc = crc.anybits?(0x80) ? ((crc << 1) ^ 0x31) : (crc << 1)
|
|
134
134
|
crc &= 0xFF
|
|
135
135
|
end
|
|
136
136
|
end
|
|
@@ -66,14 +66,12 @@ module Dredger
|
|
|
66
66
|
# For production, use hardware interrupts or kernel GPIO edge detection
|
|
67
67
|
while Time.now - start_time < duration
|
|
68
68
|
current_state = @gpio.read(pin_label)
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
# Detect rising edge (0 -> 1 transition)
|
|
71
|
-
if current_state == 1 && last_state
|
|
72
|
-
|
|
73
|
-
end
|
|
74
|
-
|
|
71
|
+
pulses += 1 if current_state == 1 && last_state.zero?
|
|
72
|
+
|
|
75
73
|
last_state = current_state
|
|
76
|
-
|
|
74
|
+
|
|
77
75
|
# Small sleep to reduce CPU usage
|
|
78
76
|
# Trade-off: Higher sleep = lower CPU, but may miss pulses
|
|
79
77
|
# For accurate counting, use interrupts instead
|
data/lib/dredger/iot/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dredger-iot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Mad Botter INC
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-03-22 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: ffi
|
|
@@ -26,7 +27,8 @@ dependencies:
|
|
|
26
27
|
description: |
|
|
27
28
|
Dredger-IoT provides FFI-based GPIO and I2C access for embedded Linux systems like Beaglebone Black.
|
|
28
29
|
Features include: libgpiod GPIO backend, Linux i2c-dev I2C backend, simulation backends for testing,
|
|
29
|
-
sensor drivers (
|
|
30
|
+
sensor drivers (BME280, DS18B20, SHT31, BH1750, TSL2561, INA219, ADXL345, SCD30, YF-S201, NEO-6M),
|
|
31
|
+
Beaglebone and Raspberry Pi pin label mapping, and
|
|
30
32
|
scheduling utilities for periodic polling and exponential backoff.
|
|
31
33
|
email:
|
|
32
34
|
- opensource@themadbotter.com
|
|
@@ -91,7 +93,7 @@ metadata:
|
|
|
91
93
|
documentation_uri: https://github.com/TheMadBotterINC/dredger-iot/blob/master/README.md
|
|
92
94
|
rubygems_mfa_required: 'true'
|
|
93
95
|
keywords: iot, embedded, linux, gpio, i2c, beaglebone, raspberry-pi, hardware, sensors,
|
|
94
|
-
|
|
96
|
+
bme280, ds18b20, sht31, bh1750, tsl2561, ina219, adxl345, scd30, libgpiod, automation
|
|
95
97
|
post_install_message: "\n ═══════════════════════════════════════════════════════════════════\n
|
|
96
98
|
\ \n _______________
|
|
97
99
|
\ \n | DREDGER-IoT | \n
|
|
@@ -106,13 +108,13 @@ post_install_message: "\n ═════════════════
|
|
|
106
108
|
\ | \n |_____________________________| \n
|
|
107
109
|
\ ~~~ \\ // ~~~ \n \\_______________//
|
|
108
110
|
\ \n ═══════════════════════════════════════════════════════════════════\nHardware
|
|
109
|
-
Integration for Embedded Linux v0.3.
|
|
111
|
+
Integration for Embedded Linux v0.3.2\n ═══════════════════════════════════════════════════════════════════\n\n
|
|
110
112
|
\ \U0001F389 Thanks for installing!\n\n \U0001F4DA Hardware Setup (kernel modules
|
|
111
113
|
& permissions):\n https://github.com/TheMadBotterINC/dredger-iot#hardware-setup\n\n
|
|
112
114
|
\ \U0001F680 Quick Start:\n require 'dredger/iot'\n gpio = Dredger::IoT::Bus::Auto.gpio\n
|
|
113
115
|
\ i2c = Dredger::IoT::Bus::Auto.i2c\n\n \U0001F4A1 Supported Sensors:\n
|
|
114
|
-
\
|
|
115
|
-
|
|
116
|
+
\ BME280, DS18B20, SHT31, INA219, ADXL345, SCD30, and more\n\n \U0001F4D6
|
|
117
|
+
Full Documentation:\n https://github.com/TheMadBotterINC/dredger-iot\n\n"
|
|
116
118
|
rdoc_options: []
|
|
117
119
|
require_paths:
|
|
118
120
|
- lib
|
|
@@ -127,7 +129,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
127
129
|
- !ruby/object:Gem::Version
|
|
128
130
|
version: '0'
|
|
129
131
|
requirements: []
|
|
130
|
-
rubygems_version: 3.
|
|
132
|
+
rubygems_version: 3.4.19
|
|
133
|
+
signing_key:
|
|
131
134
|
specification_version: 4
|
|
132
135
|
summary: Generic hardware integration for embedded Linux (GPIO, I2C) with sensor drivers.
|
|
133
136
|
test_files: []
|