diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..0a94e5e --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,5 @@ +## 0.4.0 + +IMPROVEMENTS: + + * Added support for mac address additions (optional) to emitters: https://github.com/myoung34/tilty/pull/17 diff --git a/README.md b/README.md index e30c1eb..5964fd1 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ sleep_interval = 1 url = http://www.foo.com headers = {"Content-Type": "application/json"} payload_template = {"color": "{{ color }}", "gravity": {{ gravity }}, "temp": {{ temp }}, "timestamp": "{{ timestamp }}"} +# optional payload to include mac address +# payload_template = {"color": "{{ color }}", "gravity": {{ gravity }}, "mac": {{ mac }}, "temp": {{ temp }}, "timestamp": "{{ timestamp }}"} method = POST # Brewstat.us example @@ -54,6 +56,10 @@ port = 80 database = tilty gravity_payload_template = {"measurement": "gravity", "tags": {"color": "{{ color }}"}, "fields": {"value": {{ gravity }}}} temperature_payload_template = {"measurement": "temperature", "tags": {"color": "{{ color }}"}, "fields": {"value": {{ temp }}}} +# optional payload to include mac address +# gravity_payload_template = {"measurement": "gravity", "tags": {"color": "{{ color }}", "mac": "{{ mac }}"}, "fields": {"value": {{ gravity }}}} +# temperature_payload_template = {"measurement": "temperature", "tags": {"color": "{{ color }}", "mac": "{{ mac }}"}, "fields": {"value": {{ temp }}}} +# `% curl -s -G 'http://influxdb.service.consul:8086/query?pretty=true' --data-urlencode "db=tilty" --data-urlencode 'q=SELECT "value", "mac", "color" FROM "autogen"."gravity"' | jq '.results[].series[].values[0]'` [datadog] # Note: make sure that the dd agent has DD_DOGSTATSD_NON_LOCAL_TRAFFIC=true diff --git a/pyproject.toml b/pyproject.toml index 40c8dca..1158a0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "Tilty" -version = "0.3.4" +version = "0.4.0" description = "A pluggable system to receive and transmit bluetooth events from the Tilt Hydrometer" authors = ["Marcus Young <3vilpenguin@gmail.com>"] license = "MIT" diff --git a/setup.py b/setup.py index 46f428a..1f4e5ad 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ long_description=long_description, long_description_content_type="text/markdown", py_modules=['tilty', 'blescan'], - version='0.3.4', + version='0.4.0', packages=find_packages(exclude=['tests*']), install_requires=[ 'Click', diff --git a/tests/mock_config_parser_mac.py b/tests/mock_config_parser_mac.py new file mode 100644 index 0000000..1857a32 --- /dev/null +++ b/tests/mock_config_parser_mac.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +class MockConfigParserMac: + def __init__(self, section): + self.section = section + + def __getitem__(self, key): + if self.section == 'webhook': + return { + 'url': 'http://www.google.com', + 'headers': '{"Content-Type": "application/json"}', + 'payload_template': '{"color": "{{ color }}", "gravity": {{ gravity }}, "temp": {{ temp }}, "mac": "{{ mac }}", "timestamp": "{{ timestamp }}"}', # noqa + 'method': 'GET' + } + if self.section == 'influxdb': + return { + 'url': 'http://www.google.com', + 'database': 'foo', + 'gravity_payload_template': 'gravity,mac={{ mac }} color={{ color }} value={{ gravity }} {{timestamp}}', # noqa + 'temperature_payload_template': 'temperature,scale=fahrenheit,mac={{ mac }} color={{ color }} value={{ temp }} {{timestamp}}', # noqa + } + if self.section == 'datadog': + return { + 'host': 'http://api.datadog.com', + 'port': '8120', + } + return None + + def has_section(self, *args, **kwargs): + return self.section in args diff --git a/tests/test_cli.py b/tests/test_cli.py index d729846..fdff2df 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -53,7 +53,7 @@ def test_cli_no_params_no_data( assert result.exit_code == 0 assert result.output == 'Scanning for Tilt data...\n' # noqa -@mock.patch('tilty.blescan.get_events', return_value=[{'uuid': 'a495bb30c5b14b44b5121370f02d74de', 'major': 60, 'minor': 1053}]) # noqa +@mock.patch('tilty.blescan.get_events', return_value=[{'mac': '00:0a:95:9d:68:16', 'uuid': 'a495bb30c5b14b44b5121370f02d74de', 'major': 60, 'minor': 1053}]) # noqa @mock.patch('tilty.blescan.hci_le_set_scan_parameters') # noqa @mock.patch('tilty.blescan.hci_enable_le_scan') # noqa def test_cli_no_params_success( @@ -64,4 +64,4 @@ def test_cli_no_params_success( runner = CliRunner() result = runner.invoke(cli.run, []) assert result.exit_code == 0 - assert "Scanning for Tilt data...\n{'color': 'Black', 'gravity': 1.053, 'temp': 60, 'timestamp'" in result.output# noqa + assert "Scanning for Tilt data...\n{'color': 'Black', 'gravity': 1.053, 'temp': 60, 'mac': '00:0a:95:9d:68:16', 'timestamp'" in result.output# noqa diff --git a/tests/test_datadog.py b/tests/test_datadog.py index 2aab82a..a66dbe7 100644 --- a/tests/test_datadog.py +++ b/tests/test_datadog.py @@ -16,12 +16,21 @@ def test_datadog( 'temperature': '55', 'gravity': '1054', 'color': 'black', + 'mac': '00:0a:95:9d:68:16', } datadog.Datadog(config=config).emit() mock_statsd_init.mock_calls == [ mock.call(statsd_host='http://statsd.google.com', statsd_port='8130') ] assert mock_statsd_client.mock_calls == [ - mock.call.gauge('tilty.temperature', '55', tags=['color:black']), - mock.call.gauge('tilty.gravity', '1054', tags=['color:black']), + mock.call.gauge( + 'tilty.temperature', + '55', + tags=['color:black', 'mac:00:0a:95:9d:68:16'] + ), + mock.call.gauge( + 'tilty.gravity', + '1054', + tags=['color:black', 'mac:00:0a:95:9d:68:16'] + ), ] diff --git a/tests/test_tilty.py b/tests/test_tilty.py index 3138178..7ef7d95 100644 --- a/tests/test_tilty.py +++ b/tests/test_tilty.py @@ -2,6 +2,7 @@ from unittest import mock from mock_config_parser import MockConfigParser +from mock_config_parser_mac import MockConfigParserMac from tilty import tilt_device, tilty @@ -21,7 +22,13 @@ def test_scan_for_tilt_data_parse_webhook( config = MockConfigParser('webhook') tilty.emit( config, - {'color': 'black', 'gravity': 1, 'temp': 32, 'timestamp': 155558888} + { + 'color': 'black', + 'gravity': 1, + 'temp': 32, + 'mac': '00:0a:95:9d:68:16', + 'timestamp': 155558888 + } ) assert mock_webhook.mock_calls == [ mock.call( @@ -36,6 +43,34 @@ def test_scan_for_tilt_data_parse_webhook( ] +@mock.patch('tilty.emitters.webhook.Webhook') +def test_scan_for_tilt_data_parse_webhook_with_mac( + mock_webhook, +): + config = MockConfigParserMac('webhook') + tilty.emit( + config, + { + 'color': 'black', + 'gravity': 1, + 'temp': 32, + 'mac': '00:0a:95:9d:68:16', + 'timestamp': 155558888 + } + ) + assert mock_webhook.mock_calls == [ + mock.call( + config={ + 'url': 'http://www.google.com', + 'headers': {'Content-Type': 'application/json'}, + 'method': 'GET', + 'payload': {'color': 'black', 'gravity': 1, 'temp': 32, 'mac': '00:0a:95:9d:68:16', 'timestamp': '155558888'} # noqa + } + ), + mock.call().emit() + ] + + @mock.patch('tilty.emitters.influxdb.InfluxDB') def test_scan_for_tilt_data_parse_influxdb( mock_influxdb, @@ -43,7 +78,13 @@ def test_scan_for_tilt_data_parse_influxdb( config = MockConfigParser('influxdb') tilty.emit( config, - {'color': 'black', 'gravity': 1, 'temp': 32, 'timestamp': 155558888} + { + 'color': 'black', + 'gravity': 1, + 'temp': 32, + 'mac': '00:0a:95:9d:68:16', + 'timestamp': 155558888 + } ) assert mock_influxdb.mock_calls == [ mock.call( @@ -58,6 +99,34 @@ def test_scan_for_tilt_data_parse_influxdb( ] +@mock.patch('tilty.emitters.influxdb.InfluxDB') +def test_scan_for_tilt_data_parse_influxdb_with_mac( + mock_influxdb, +): + config = MockConfigParserMac('influxdb') + tilty.emit( + config, + { + 'color': 'black', + 'gravity': 1, + 'temp': 32, + 'mac': '00:0a:95:9d:68:16', + 'timestamp': 155558888 + } + ) + assert mock_influxdb.mock_calls == [ + mock.call( + config={ + 'url': 'http://www.google.com', + 'database': 'foo', + 'temperature_payload': 'temperature,scale=fahrenheit,mac=00:0a:95:9d:68:16 color=black value=32 155558888', # noqa + 'gravity_payload': 'gravity,mac=00:0a:95:9d:68:16 color=black value=1 155558888' # noqa + } + ), + mock.call().emit() + ] + + @mock.patch('tilty.emitters.datadog.Datadog') def test_scan_for_tilt_data_parse_datadog( mock_dd, @@ -65,9 +134,15 @@ def test_scan_for_tilt_data_parse_datadog( config = MockConfigParser('datadog') tilty.emit( config, - {'color': 'black', 'gravity': 1, 'temp': 32, 'timestamp': 155558888} + { + 'color': 'black', + 'gravity': 1, + 'temp': 32, + 'mac': '00:0a:95:9d:68:16', + 'timestamp': 155558888 + } ) assert mock_dd.mock_calls == [ - mock.call(config={'host': 'http://api.datadog.com', 'port': '8120', 'gravity': 1, 'temperature': 32, 'color': 'black'}), # noqa + mock.call(config={'host': 'http://api.datadog.com', 'port': '8120', 'gravity': 1, 'mac': '00:0a:95:9d:68:16', 'temperature': 32, 'color': 'black'}), # noqa mock.call().emit() ] diff --git a/tilty/emitters/datadog.py b/tilty/emitters/datadog.py index 556d63f..46bf2b0 100644 --- a/tilty/emitters/datadog.py +++ b/tilty/emitters/datadog.py @@ -20,6 +20,7 @@ def __init__(self, config): self.temperature = config['temperature'] self.gravity = config['gravity'] self.color = config['color'] + self.mac = config['mac'] options = { 'statsd_host': config['host'], 'statsd_port': safe_get_key(config, 'port', 8125), @@ -32,14 +33,20 @@ def emit(self, **kwargs): # pylint: disable=no-self-use,unused-argument Args: """ LOGGER.info('[datadog] posting temperature data') + tags = [f"color:{self.color}"] + if self.mac: + tags = [ + f"color:{self.color}", + f"mac:{self.mac}", + ] statsd.gauge( 'tilty.temperature', self.temperature, - tags=[f"color:{self.color}"] + tags=tags, ) LOGGER.info('[datadog] posting gravity data') statsd.gauge( 'tilty.gravity', self.gravity, - tags=[f"color:{self.color}"] + tags=tags, ) diff --git a/tilty/tilt_device.py b/tilty/tilt_device.py index 7c2521c..47224e3 100644 --- a/tilty/tilt_device.py +++ b/tilty/tilt_device.py @@ -44,6 +44,7 @@ def scan_for_tilt_data(self): 'color': constants.TILT_DEVICES[beacon['uuid']], 'gravity': float(beacon['minor']/1000), 'temp': beacon['major'], + 'mac': beacon['mac'], 'timestamp': datetime.now().isoformat(), } diff --git a/tilty/tilty.py b/tilty/tilty.py index 2cf90fe..570216a 100644 --- a/tilty/tilty.py +++ b/tilty/tilty.py @@ -30,6 +30,7 @@ def emit(config, tilt_data): 'payload': json.loads(_template.render( color=tilt_data['color'], gravity=tilt_data['gravity'], + mac=tilt_data['mac'], temp=tilt_data['temp'], timestamp=tilt_data['timestamp'], )), @@ -53,12 +54,14 @@ def emit(config, tilt_data): 'temperature_payload': _temperature_template.render( color=tilt_data['color'], gravity=tilt_data['gravity'], + mac=tilt_data['mac'], temp=tilt_data['temp'], timestamp=tilt_data['timestamp'], ), 'gravity_payload': _gravity_template.render( color=tilt_data['color'], gravity=tilt_data['gravity'], + mac=tilt_data['mac'], temp=tilt_data['temp'], timestamp=tilt_data['timestamp'], ), @@ -75,6 +78,7 @@ def emit(config, tilt_data): 'host': config['datadog']['host'], 'port': config['datadog']['port'], 'gravity': tilt_data['gravity'], + 'mac': tilt_data['mac'], 'temperature': tilt_data['temp'], 'color': tilt_data['color'], }