Skip to content

Commit

Permalink
Merge pull request #423 from thorrak/dev
Browse files Browse the repository at this point in the history
Update to latest dev
  • Loading branch information
thorrak authored Feb 15, 2020
2 parents b9d4c87 + 55e44ce commit 50dbec9
Show file tree
Hide file tree
Showing 24 changed files with 1,017 additions and 32 deletions.
4 changes: 2 additions & 2 deletions app/api/lcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def getLCD(req, device_id):

def getPanel(req, device_id):
def temp_text(temp, temp_format):
if temp == 0:
if (temp is None) or (temp == 0):
return "--° {}".format(temp_format)
else:
return "{}° {}".format(temp, temp_format)
return "{:.1f}° {}".format(temp, temp_format)

ret = []
try:
Expand Down
15 changes: 8 additions & 7 deletions app/device_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ def clean_device_name(self):
else:
device_name = self.cleaned_data['device_name']

try:
existing_device = BrewPiDevice.objects.get(device_name=device_name)
raise forms.ValidationError("A device already exists with the name {}".format(device_name))

except ObjectDoesNotExist:
# There was no existing device - we're good.
return device_name
# try:
# existing_device = BrewPiDevice.objects.get(device_name=device_name)
# raise forms.ValidationError("A device already exists with the name {}".format(device_name))
#
# except ObjectDoesNotExist:
# # There was no existing device - we're good.
# return device_name
return device_name

def clean(self):
cleaned_data = self.cleaned_data
Expand Down
26 changes: 22 additions & 4 deletions docs/source/develop/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,36 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) because it



[Unversioned] - Fixes
~~~~~~~~~~~~~~~~~~~~~
[2019-02-15] - ThingSpeak and Grainfather Support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Added
---------------------

- Added support for pushing data to ThingSpeak (thanks @johndoyle!)
- Added support for pushing data to Grainfather (thanks @mp-se!)


Changed
---------------------

- Gravity sensors attached to BrewPi controllers will now send those controller's temps to Brewfather
- An explicit error message will now be displayed when a user attempts to manually access the ispindel endpoint


Fixed
---------------------

- Fixed where Fahrenheit readings coming from an iSpindel could be improperly reconverted to Fahrenheit

- Lock temperature display on dashboard panels to one decimal place
- Allow updates to controller settings when controller name isn't changing (for real this time)
- Fix bug that would default all Tilts to 'Bluetooth' even when a TiltBridge was selected
- Fixed issue where Tilt readings were not being properly decoded (Thanks NecroBrews!)
- Fixed issue where dashboard panels were not being updated (Thanks NecroBrews!)


[2019-12-15] - Brewer's Friend, Brewfather, and MacOS BLE Support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Added
---------------------
Expand Down
73 changes: 70 additions & 3 deletions docs/source/develop/push_support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ future - support pushing via TCP (sockets)).
Supported "Push" Targets
------------------------------

Fermentrack currently supports three push targets:
Fermentrack currently supports five push targets:

- **"Generic" Push Target** - Fermentrack's "native" push format - Pushes both specific gravity & temperature data
- **Brewer's Friend** - Fermentrack's "native" push format - Pushes both specific gravity & temperature data
- **Brewfather** - Fermentrack's "native" push format - Pushes both specific gravity & temperature data
- **Brewer's Friend** - Pushes both specific gravity & temperature data associated with gravty sensors
- **Brewfather** - Pushes both specific gravity & temperature data associated with gravity sensors, as well as temperature data from BrewPi controllers with gravity sensors attached
- **ThingSpeak** - Pushes temperature data
- **Grainfather** - iSpindel push format - Pushes both specific gravity & temperature data from gravity sensors



Expand Down Expand Up @@ -92,6 +94,71 @@ Fermentrack supports pushing data from specific gravity sensors to Brewfather us

Within 60 seconds, Fermentrack will begin sending data from your gravity sensor to Brewfather. This data can be seen on the `Devices <https://web.brewfather.app/#/tabs/devices/devices>`_ page.

**NOTE** - If your gravity sensor is attached to a BrewPi controller, the temperature readings from that controller will be used instead of the ones from the gravity sensor.


ThingSpeak Support
***********************

Fermentrack supports pushing data from specific sensors to a ThinkSpeak Channel. The Channel Speak API is fixed to receive fields in the channel, so the designation of each channel is already defined. This means that Field 1 is always Beer Name, Field 2 is Sensor Name, etc. To configure:

#. Log into Fermentrack and click the "gear" icon in the upper right
#. Click "Add ThingSpeak Push Target" at the bottom of the page
#. Now log into your ThingSpeak acount and on the My Channels Page select New Channel
#. Enter the data below in
::
Name - Give your Channel a Name
Description - Give your Channel a Description
Field 1 - Beer Name
Field 2 - Sensor Name
Field 3 - Temp Format
Field 4 - Beer Temp
Field 5 - Fridge Temp
Field 6 - Room Temp
Field 7 - Beer Gravity

Feel free to fill out the optional elements but only the 'field' values above are sent. The values entered are just labels for the data sent and can be customised. For example you can change 'Beer Temp' to 'My Beer (°C)'.


#. At the bottom of the page, select 'Save Channel'
#. Copy the "Write API Key" from the "API Keys" section
#. Within Fermentrack, paste the API Key you just copied into the "API Key" field
#. Set the desired push frequency and select the gravity sensor from which you want to push data
#. Click "Add Push Target"

Within 60 seconds, Fermentrack will begin sending data from to the ThingSpeak Channel. This data can be seen on the ThingSpeak 'Private View' tab in the channel page.

Grainfather Support
***********************

Fermentrack supports pushing data from specific gravity sensors (Gravity & Temperature) to Grainfather using the brew tracking API. To configure:

#. Log into your Grainfather account and select Equipment.
#. Add a Fermentation device and select iSpindel as device type. Fermentrack will push data in this format independant of what your device is. Copy the logging URL.
#. The second thing you need to do is to go to an active brew and link the device to a brew session. This is done under the headline fermentration tracking and the function "Add Tracking Device". Make note of the Name value (this is the brew ID).
#. Log into Fermentrack and click the "gear" icon in the upper right
#. Click "Add Grainfather Push Target" at the bottom of the page
#. Within Fermentrack, paste the Logging URL you just copied into the "Logging URL" field and enter the name (brew id) under the "gf_name" field.
#. Set the desired push frequency and select the gravity sensor from which you want to push data
#. Click "Add Push Target"

Within 60 seconds, Fermentrack will begin sending data from your gravity sensor to Grainfather. This data can be seen in your Grainfather account under Equipment or the Brew Session.

Grainfather Support
***********************

Fermentrack supports pushing data from specific gravity sensors (Gravity & Temperature) to Grainfather using the brew tracking API. To configure:

#. Log into your Grainfather account and select Equipment.
#. Add a Fermentation device and select iSpindel as device type. Fermentrack will push data in this format independant of what your device is. Copy the logging URL.
#. The second thing you need to do is to go to an active brew and link the device to a brew session. This is done under the headline fermentration tracking and the function "Add Tracking Device". Make note of the Name value (this is the brew ID).
#. Log into Fermentrack and click the "gear" icon in the upper right
#. Click "Add Grainfather Push Target" at the bottom of the page
#. Within Fermentrack, paste the Logging URL you just copied into the "Logging URL" field and enter the name (brew id) under the "gf_name" field.
#. Set the desired push frequency and select the gravity sensor from which you want to push data
#. Click "Add Push Target"

Within 60 seconds, Fermentrack will begin sending data from your gravity sensor to Grainfather. This data can be seen in your Grainfather account under Equipment or the Brew Session.


Implementation Notes
Expand Down
12 changes: 10 additions & 2 deletions external_push/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.contrib import admin

from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget
from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget, ThingSpeakPushTarget, GrainfatherPushTarget


@admin.register(GenericPushTarget)
Expand All @@ -13,4 +13,12 @@ class BrewersFriendPushTargetAdmin(admin.ModelAdmin):

@admin.register(BrewfatherPushTarget)
class BrewfatherPushTargetAdmin(admin.ModelAdmin):
list_display = ('gravity_sensor_to_push', 'status', 'push_frequency')
list_display = ('gravity_sensor_to_push', 'status', 'push_frequency')

@admin.register(ThingSpeakPushTarget)
class ThingSpeakPushTargetAdmin(admin.ModelAdmin):
list_display = ('name', 'status')

@admin.register(GrainfatherPushTarget)
class GrainfatherPushTargetAdmin(admin.ModelAdmin):
list_display = ('gravity_sensor_to_push', 'status', 'push_frequency')
14 changes: 13 additions & 1 deletion external_push/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django import forms

from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget
from external_push.models import GenericPushTarget, BrewersFriendPushTarget, BrewfatherPushTarget, ThingSpeakPushTarget, GrainfatherPushTarget
from django.core import validators
import fermentrack_django.settings as settings

Expand All @@ -24,3 +24,15 @@ class BrewfatherPushTargetModelForm(ModelForm):
class Meta:
model = BrewfatherPushTarget
fields = ['gravity_sensor_to_push', 'push_frequency', 'logging_url']

class ThingSpeakPushTargetModelForm(ModelForm):
class Meta:
model = ThingSpeakPushTarget
fields = ['name', 'push_frequency', 'api_key', 'brewpi_to_push']



class GrainfatherPushTargetModelForm(ModelForm):
class Meta:
model = GrainfatherPushTarget
fields = ['gravity_sensor_to_push', 'push_frequency', 'logging_url', 'gf_name']
34 changes: 34 additions & 0 deletions external_push/migrations/0005_ThingSpeak_Support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2019-11-29 21:31
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('gravity', '0004_BrewersFriend_Support'),
('external_push', '0004_Brewfather_Support'),
]

operations = [
migrations.CreateModel(
name='ThingSpeakPushTarget',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Unique name for this push target', max_length=48, unique=True)),
('status', models.CharField(choices=[('active', 'Active'), ('disabled', 'Disabled'), ('error', 'Error')], default='active', help_text='Status of this push target', max_length=24)),
('push_frequency', models.IntegerField(choices=[(901, '15 minutes'), (1801, '30 minutes'), (3601, '1 hour')], default=900, help_text='How often to push data to the target')),
('api_key', models.CharField(default='', help_text='Brewers Friend API Key', max_length=256)),
('brewpi_to_push_id', models.ForeignKey(blank=True, default=None, help_text="BrewPi Devices to push (ignored if 'all' devices selected)", related_name='push_targets', to='app.BrewPiDevice')),
('error_text', models.TextField(blank=True, default='', help_text='The error (if any) encountered on the last push attempt', null=True)),
('last_triggered', models.DateTimeField(auto_now_add=True, help_text='The last time we pushed data to this target')),
],
options={
'verbose_name': 'ThingSpeak Push Target',
'verbose_name_plural': 'ThingSpeak Push Targets',
},
)
]
34 changes: 34 additions & 0 deletions external_push/migrations/0006_Grainfather_Support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.27 on 2019-12-23 13:58
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('gravity', '0004_BrewersFriend_Support'),
('external_push', '0005_ThingSpeak_Support'),
]

operations = [
migrations.CreateModel(
name='GrainfatherPushTarget',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.CharField(choices=[('active', 'Active'), ('disabled', 'Disabled'), ('error', 'Error')], default='active', help_text='Status of this push target', max_length=24)),
('push_frequency', models.IntegerField(choices=[(901, '15 minutes'), (1801, '30 minutes'), (3601, '1 hour')], default=900, help_text='How often to push data to the target')),
('logging_url', models.CharField(default='', help_text='Grainfather Logging URL', max_length=256)),
('gf_name', models.CharField(default='', help_text='Grainfather brew id (number)', max_length=256)),
('error_text', models.TextField(blank=True, default='', help_text='The error (if any) encountered on the last push attempt', null=True)),
('last_triggered', models.DateTimeField(auto_now_add=True, help_text='The last time we pushed data to this target')),
('gravity_sensor_to_push', models.ForeignKey(help_text='Gravity Sensor to push (create one push target per sensor to push)', on_delete=django.db.models.deletion.CASCADE, related_name='grainfather_push_target', to='gravity.GravitySensor')),
],
options={
'verbose_name': 'Grainfather Push Target',
'verbose_name_plural': 'Grainfather Push Targets',
},
),
]
36 changes: 36 additions & 0 deletions external_push/migrations/0007_fix_thingspeak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.27 on 2020-02-03 04:28
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('app', '0009_auto_20180709_0256'),
('external_push', '0006_Grainfather_Support'),
]

operations = [
migrations.RemoveField(
model_name='thingspeakpushtarget',
name='brewpi_to_push_id',
),
migrations.AddField(
model_name='thingspeakpushtarget',
name='brewpi_to_push',
field=models.ForeignKey(blank=True, default=None, help_text="BrewPi Devices to push (ignored if 'all' devices selected)", on_delete=django.db.models.deletion.CASCADE, related_name='thingspeak_push_targets', to='app.BrewPiDevice'),
),
migrations.AlterField(
model_name='thingspeakpushtarget',
name='api_key',
field=models.CharField(default='', help_text='ThingSpeak Channel API Key', max_length=256),
),
migrations.AlterField(
model_name='thingspeakpushtarget',
name='push_frequency',
field=models.IntegerField(choices=[(59, '1 minute'), (119, '2 minutes'), (299, '5 minutes'), (599, '10 minutes'), (899, '15 minutes'), (1799, '30 minutes'), (3599, '1 hour')], default=900, help_text='How often to push data to the target'),
),
]
Loading

0 comments on commit 50dbec9

Please sign in to comment.