feat: update layout

This commit is contained in:
Wlad Meixner 2022-09-29 14:03:41 +02:00
parent 636e6cdf17
commit f97b57d9c9
18 changed files with 293 additions and 118 deletions

BIN
app/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '15.0'
platform :ios, '15.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:grow_me_app/main.dart';
class Button extends StatelessWidget {
const Button(this.text, this.onTap, {super.key});
@ -16,10 +17,14 @@ class Button extends StatelessWidget {
margin: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.lightGreen[500],
color: primarySwatch,
shape: BoxShape.rectangle,
),
child: Center(child: Text(text)),
child: Center(
child: Text(
text,
style: TextStyle(color: lightBackgroundColor),
)),
),
);
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:grow_me_app/main.dart';
class GrowMeCard extends StatelessWidget {
const GrowMeCard({this.child, super.key});
@ -13,13 +14,13 @@ class GrowMeCard extends StatelessWidget {
margin: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: Colors.white,
color: lightBackgroundColor,
shape: BoxShape.rectangle,
border: Border.all(
color: Colors.grey.shade200, width: 2, style: BorderStyle.solid),
color: lightBackgroundColor, width: 2, style: BorderStyle.solid),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
color: Colors.black.withOpacity(0.2),
spreadRadius: 3,
blurRadius: 15,
offset: const Offset(0, 10), // changes position of shadow

View File

@ -35,19 +35,19 @@ class DeviceCarouselState extends State<DeviceCarousel> {
backgroundColor: device.isConnected
? Colors.lightGreen
: Colors.grey[400],
backgroundImage:
AssetImage('assets/prototype-render.png'),
backgroundImage: const AssetImage(
'assets/images/prototype-render.png'),
radius: 150.0,
),
...(!device.isConnected
? [
const SizedBox(height: 25),
Text("Lost connection..."),
const Text("Lost connection..."),
]
: [
const SizedBox(height: 25),
]),
Spacer(),
const Spacer(),
DeviceActionSheet(device: device, model: model)
].toList(),
))));

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:grow_me_app/components/bottom_sheet.dart';
import 'package:grow_me_app/components/button.dart';
import 'package:grow_me_app/components/connection_sheet.dart';
import 'package:grow_me_app/components/device_model.dart';
import 'package:grow_me_app/message.pb.dart';
@ -9,7 +10,6 @@ import 'dart:developer' as developer;
class DeviceDebugView extends StatefulWidget {
const DeviceDebugView({super.key, required this.device});
final LinkedDevice device;
@override
@ -19,52 +19,6 @@ class DeviceDebugView extends StatefulWidget {
class DeviceDebugViewState extends State<DeviceDebugView> {
final List<double> _motorStepValues = [20, 20, 40, 50, 60, 20];
Future<BluetoothCharacteristic?> _getCharacteristic() async {
var device = widget.device.device;
try {
var services = await device!.discoverServices();
BluetoothService service = services.firstWhere(
(element) => element.uuid.toString() == bleServiceName.toLowerCase());
if (service == null) {
developer.log("device does not offer motor control service",
name: "device.debug");
}
return service.characteristics.first;
} catch (e) {
return null;
}
}
void _resetMotorPosition(int index) async {
var ch = await _getCharacteristic();
if (ch == null) {
return;
}
var cmd = Command(reset: ResetMotorPositionCommand());
await ch.write(cmd.writeToBuffer(), withoutResponse: false);
await ch.setNotifyValue(true);
}
void _sendMotorControl(int index, bool isDecriment) async {
var ch = await _getCharacteristic();
if (ch == null) {
return;
}
// find motor control service
int factor = isDecriment ? -1 : 1;
var cmd = Command(
move:
MoveMotorCommand(target: factor * _motorStepValues[index].toInt()));
await ch.write(cmd.writeToBuffer(), withoutResponse: false);
await ch.setNotifyValue(true);
}
@override
Widget build(BuildContext context) {
return Column(children: [
@ -74,9 +28,20 @@ class DeviceDebugViewState extends State<DeviceDebugView> {
Text("Motor ${entry.key + 1}"),
Row(
children: [
(widget.device.motorStatus == null
? Container()
: Row(
children: widget.device.motorStatus!.status
.asMap()
.entries
.map((e) => Column(
children: [Text("M${e.key} pos: ${e.value}")],
))
.toList(),
)),
IconButton(
onPressed: () {
_resetMotorPosition(entry.key);
widget.device.resetMotorPosition(entry.key);
},
icon: const Icon(Icons.replay_outlined)),
const Spacer(),
@ -94,17 +59,24 @@ class DeviceDebugViewState extends State<DeviceDebugView> {
const Spacer(),
IconButton(
onPressed: () {
_sendMotorControl(entry.key, true);
widget.device.moveMotor(
entry.key, -1 * _motorStepValues[entry.key].toInt());
},
icon: const Icon(Icons.remove_circle)),
IconButton(
onPressed: () {
_sendMotorControl(entry.key, false);
widget.device.moveMotor(
entry.key, _motorStepValues[entry.key].toInt());
},
icon: const Icon(Icons.add_circle))
],
)
])),
Button("Reload state", (() {
widget.device.fetchStatusUpdate().then((value) {
setState(() {});
});
}))
]);
}
}

View File

@ -7,15 +7,32 @@ import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:grow_me_app/app.pb.dart';
import 'package:grow_me_app/components/connection_sheet.dart';
import 'package:grow_me_app/message.pbserver.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:collection/collection.dart';
const storageKey = "known-devices";
const Map<String, String> deviceCharacteristics = {
"M1": "68023a4e-e253-46e4-a439-f716b3702ae1",
"M2": "a9102165-7b40-4cce-9008-f4af28b5ac5e",
"M3": "4e9cad83-71d8-40c1-8876-53c1cd5fe27e",
"M4": "e0b49f4b-d7b0-4336-8562-41a16e16e8e6",
"M5": "5f01e609-182f-45fe-aa23-45c12b82e2df",
"M6": "09da8768-b6ba-4b4e-b91f-65d624581d48",
"info": "9c05490f-cc74-4fd2-8d16-fb228e3f2270"
};
class LinkedDevice {
BluetoothDevice? _device;
MotorStatus? _motorStatus;
KnownDevice description;
BluetoothDeviceState _status = BluetoothDeviceState.disconnected;
MotorStatus? get motorStatus {
return _motorStatus;
}
BluetoothDeviceState get status {
return _status;
}
@ -43,11 +60,80 @@ class LinkedDevice {
LinkedDevice(this.description, BluetoothDevice? device) {
this.device = device;
}
Future<BluetoothCharacteristic?> _getCharacteristic(String uuid) async {
if (_device == null) {
return null;
}
try {
var services = await _device!.discoverServices();
BluetoothService service = services.firstWhere(
(element) => element.uuid.toString() == bleServiceName.toLowerCase());
if (service == null) {
log("device does not offer motor control service",
name: "device.debug");
}
// find selected characteristic
return service.characteristics
.firstWhereOrNull((ch) => ch.uuid.toString() == uuid.toLowerCase());
} catch (e) {
return null;
}
}
Future<bool> fetchStatusUpdate() async {
var ch = await _getCharacteristic(deviceCharacteristics["info"]!);
if (ch == null) {
return false;
}
var resp = await ch.read();
try {
var status = MotorStatus.fromBuffer(resp);
_motorStatus = status;
return true;
} catch (e) {
log("failed to fetch new machine status $e");
return false;
}
}
Future<bool> moveMotor(int motorIndex, int offset) async {
var ch =
await _getCharacteristic(deviceCharacteristics["M${motorIndex + 1}"]!);
if (ch == null) {
return false;
}
var cmd = Command(move: MoveMotorCommand(target: offset));
await ch.write(cmd.writeToBuffer(), withoutResponse: false);
await ch.setNotifyValue(true);
return true;
}
Future<bool> resetMotorPosition(int motorIndex) async {
var ch =
await _getCharacteristic(deviceCharacteristics["M${motorIndex + 1}"]!);
if (ch == null) {
return false;
}
var cmd = Command(reset: ResetMotorPositionCommand());
await ch.write(cmd.writeToBuffer(), withoutResponse: false);
await ch.setNotifyValue(true);
return true;
}
}
class DeviceModel extends ChangeNotifier {
List<LinkedDevice> _devices = [];
Stream<List<ScanResult>>? _scanStream = null;
UnmodifiableListView<LinkedDevice> get devices =>
UnmodifiableListView(_devices);

View File

@ -46,13 +46,14 @@ class EditDeviceViewState extends State<EditDeviceView> {
controller: _deviceNameController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter a search term',
hintText: 'Give your plant a name',
),
),
const SizedBox(height: 25),
const CircleAvatar(
backgroundColor: Colors.lightGreen,
backgroundImage: AssetImage('assets/prototype-render.png'),
backgroundImage:
AssetImage('assets/images/prototype-render.png'),
radius: 150.0,
),
const SizedBox(height: 50),

View File

@ -16,7 +16,7 @@ void main() {
create: (context) => DeviceModel(), child: const GrowMeApp()));
}
const primarySwatch = MaterialColor(0xFFE5DBCF, {
const primarySwatch = MaterialColor(0xFF273825, {
50: Color(0xFFE5E7E5),
100: Color(0xFFBEC3BE),
200: Color(0xFF939C92),
@ -28,6 +28,9 @@ const primarySwatch = MaterialColor(0xFFE5DBCF, {
800: Color(0xFF172416),
900: Color(0xFF0E170D),
});
const lightBackgroundColor = Color(0xFFE5DBCF);
const PrimaryAssentColor = Color(0x00263825);
const PrimaryDarkColor = Color(0xFF808080);
const ErroColor = Color(0xFF808080);
@ -121,15 +124,17 @@ class _MyHomePageState extends State<GrowMeHomePage> {
appBar: AppBar(
// Here we take the value from the GrowMeHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
title: const Image(
height: 50, image: AssetImage("assets/images/logo.png")),
leadingWidth: 100,
actions: [const Icon(Icons.settings)].toList(),
// actions: [const Icon(Icons.settings)].toList(),
automaticallyImplyLeading: true,
elevation: 0,
),
backgroundColor: primarySwatch,
body: Column(
children: [
const Spacer(),
const SizedBox(height: 50),
DeviceCarousel(leadingCarouselItems: [_connectionCard()]),
const Spacer(),
].toList()),

View File

@ -248,3 +248,44 @@ class ResetMotorPositionCommand extends $pb.GeneratedMessage {
void clearMotorIndex() => clearField(1);
}
class MotorStatus extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MotorStatus', createEmptyInstance: create)
..p<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'status', $pb.PbFieldType.K3)
..hasRequiredFields = false
;
MotorStatus._() : super();
factory MotorStatus({
$core.Iterable<$core.int>? status,
}) {
final _result = create();
if (status != null) {
_result.status.addAll(status);
}
return _result;
}
factory MotorStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory MotorStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
MotorStatus clone() => MotorStatus()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
MotorStatus copyWith(void Function(MotorStatus) updates) => super.copyWith((message) => updates(message as MotorStatus)) as MotorStatus; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static MotorStatus create() => MotorStatus._();
MotorStatus createEmptyInstance() => create();
static $pb.PbList<MotorStatus> createRepeated() => $pb.PbList<MotorStatus>();
@$core.pragma('dart2js:noInline')
static MotorStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MotorStatus>(create);
static MotorStatus? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get status => $_getList(0);
}

View File

@ -53,3 +53,13 @@ const ResetMotorPositionCommand$json = const {
/// Descriptor for `ResetMotorPositionCommand`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List resetMotorPositionCommandDescriptor = $convert.base64Decode('ChlSZXNldE1vdG9yUG9zaXRpb25Db21tYW5kEh4KCm1vdG9ySW5kZXgYASABKAVSCm1vdG9ySW5kZXg=');
@$core.Deprecated('Use motorStatusDescriptor instead')
const MotorStatus$json = const {
'1': 'MotorStatus',
'2': const [
const {'1': 'status', '3': 1, '4': 3, '5': 5, '10': 'status'},
],
};
/// Descriptor for `MotorStatus`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List motorStatusDescriptor = $convert.base64Decode('CgtNb3RvclN0YXR1cxIWCgZzdGF0dXMYASADKAVSBnN0YXR1cw==');

View File

@ -66,7 +66,7 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
- assets/
- assets/images/
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
@ -78,16 +78,16 @@ flutter:
fonts:
- family: Manrope
fonts:
- asset: fonts/Manrope-ExtraLight.ttf
- asset: assets/fonts/Manrope-ExtraLight.ttf
weight: 200
- asset: fonts/Manrope-Light.ttf
- asset: assets/fonts/Manrope-Light.ttf
weight: 300
- asset: fonts/Manrope-Regular.ttf
- asset: fonts/Manrope-Mediumttf
- asset: assets/fonts/Manrope-Regular.ttf
- asset: assets/fonts/Manrope-Medium.ttf
weight: 500
- asset: fonts/Manrope-SemiBold.ttf
- asset: assets/fonts/Manrope-SemiBold.ttf
weight: 600
- asset: fonts/Manrope-Bold.ttf
- asset: assets/fonts/Manrope-Bold.ttf
weight: 700
- asset: fonts/Manrope-ExtraBold.ttf
- asset: assets/fonts/Manrope-ExtraBold.ttf
weight: 800

View File

@ -19,12 +19,12 @@ struct MotorControl {
long stepTarget = 0;
long currentPosition = 0;
BLECharacteristic *bleCharacteristic = NULL;
BLECharacteristic *bleInfoCharacteristic = NULL;
MotorControl(uint8_t index, short dir, short step);
void addControlCharacteristic(BLECharacteristic *bleCharac);
void addInfoCharacteristic(BLECharacteristic *bleCharac);
void updateCurrentPosition(long newPosition);
};
class CustomBLEMotorCallback : public BLECharacteristicCallbacks {
@ -44,8 +44,8 @@ class CustomBLEMotorCallback : public BLECharacteristicCallbacks {
};
class CustomBLEMotorInfoCallback : public BLECharacteristicCallbacks {
int motorIndex;
MotorControl *controller;
MotorControl **motors;
size_t numMotors;
MotorStatus msg;
// set internal position value
@ -54,8 +54,9 @@ class CustomBLEMotorInfoCallback : public BLECharacteristicCallbacks {
void onRead(BLECharacteristic *ch);
public:
CustomBLEMotorInfoCallback(uint8_t motorIndex, MotorControl *controller) {
this->motorIndex = motorIndex;
this->controller = controller;
CustomBLEMotorInfoCallback(MotorControl *motors[]) {
this->motors = motors;
// TODO: compute dynamically
numMotors = 6;
};
};

View File

@ -11,7 +11,7 @@
/* Struct definitions */
typedef struct _MotorStatus {
int32_t totalSteps;
pb_callback_t status;
} MotorStatus;
typedef struct _MoveMotorCommand {
@ -45,15 +45,15 @@ extern "C" {
#define ProgressCommand_init_default {0}
#define MoveMotorCommand_init_default {0}
#define ResetMotorPositionCommand_init_default {0}
#define MotorStatus_init_default {0}
#define MotorStatus_init_default {{{NULL}, NULL}}
#define Command_init_zero {0, {ProgressCommand_init_zero}}
#define ProgressCommand_init_zero {0}
#define MoveMotorCommand_init_zero {0}
#define ResetMotorPositionCommand_init_zero {0}
#define MotorStatus_init_zero {0}
#define MotorStatus_init_zero {{{NULL}, NULL}}
/* Field tags (for use in manual encoding/decoding) */
#define MotorStatus_totalSteps_tag 1
#define MotorStatus_status_tag 1
#define MoveMotorCommand_target_tag 1
#define ProgressCommand_progress_tag 1
#define ResetMotorPositionCommand_motorIndex_tag 1
@ -88,8 +88,8 @@ X(a, STATIC, SINGULAR, INT32, motorIndex, 1)
#define ResetMotorPositionCommand_DEFAULT NULL
#define MotorStatus_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, INT32, totalSteps, 1)
#define MotorStatus_CALLBACK NULL
X(a, CALLBACK, REPEATED, INT32, status, 1)
#define MotorStatus_CALLBACK pb_default_field_callback
#define MotorStatus_DEFAULT NULL
extern const pb_msgdesc_t Command_msg;
@ -106,8 +106,8 @@ extern const pb_msgdesc_t MotorStatus_msg;
#define MotorStatus_fields &MotorStatus_msg
/* Maximum encoded size of messages (where known) */
/* MotorStatus_size depends on runtime parameters */
#define Command_size 13
#define MotorStatus_size 11
#define MoveMotorCommand_size 11
#define ProgressCommand_size 5
#define ResetMotorPositionCommand_size 11

View File

@ -24,5 +24,5 @@ message ResetMotorPositionCommand {
}
message MotorStatus {
int32 totalSteps = 1;
repeated int32 status = 1;
}

View File

@ -1,5 +1,7 @@
#include "MotorControl.hpp"
#include <EEPROM.h>
void CustomBLEMotorCallback::onWrite(BLECharacteristic *characteristic) {
const char *tag = "BLEMotor";
@ -32,24 +34,74 @@ void CustomBLEMotorCallback::onRead(BLECharacteristic *ch) {
ESP_LOGI("MotorCallback", "onRead");
};
struct RepeatedStatus {
int32_t *status;
int index;
size_t max_size;
};
bool status_encode(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
RepeatedStatus *def = (RepeatedStatus *)*arg;
while (def->index < def->max_size) {
int32_t status = def->status[def->index];
++def->index;
if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) {
ESP_LOGE(TAG, "failed to encode: %s", PB_GET_ERROR(stream));
return false;
}
if (!pb_encode_varint(stream, status)) {
ESP_LOGE(TAG, "failed to encode: %s", PB_GET_ERROR(stream));
return false;
}
ESP_LOGI(TAG, "written value %d", status);
}
return true;
}
void CustomBLEMotorInfoCallback::onRead(BLECharacteristic *characteristic) {
// encode message in pb format
pb_ostream_t stream = pb_ostream_from_buffer(this->buffer, sizeof(this->buffer));
this->msg.totalSteps = this->controller->currentPosition;
int32_t status[numMotors];
for (int i = 0; i < this->numMotors; i++) {
status[i] = this->motors[i]->currentPosition;
}
struct RepeatedStatus args = {.status = status, .index = 0, .max_size = this->numMotors};
msg.status.arg = &args;
msg.status.funcs.encode = status_encode;
if (!pb_encode(&stream, Command_fields, &this->msg)) {
ESP_LOGE(TAG, "failed to encode: %s", PB_GET_ERROR(&stream));
return;
}
ESP_LOGI(TAG, "encoded status msg %d", stream.bytes_written);
// encode latest value in characteristic
characteristic->setValue(buffer, stream.bytes_written);
characteristic->setNotifyProperty(true);
};
MotorControl::MotorControl(uint8_t index, short dir, short step) {
this->stepper = new A4988(MOTOR_STEPS, dir, step);
this->index = index;
int address = index * 8;
// reload position from EEPROM
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
this->currentPosition = ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) +
((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
this->stepTarget = this->currentPosition;
};
void MotorControl::addControlCharacteristic(BLECharacteristic *bleCharac) {
@ -61,11 +113,16 @@ void MotorControl::addControlCharacteristic(BLECharacteristic *bleCharac) {
this->bleCharacteristic->setCallbacks(new CustomBLEMotorCallback(index, this));
};
void MotorControl::addInfoCharacteristic(BLECharacteristic *bleCharac) {
this->bleInfoCharacteristic = bleCharac;
void MotorControl::updateCurrentPosition(long newPosition) {
currentPosition = newPosition;
int address = index * 8;
byte four = (newPosition & 0xFF);
byte three = ((newPosition >> 8) & 0xFF);
byte two = ((newPosition >> 16) & 0xFF);
byte one = ((newPosition >> 24) & 0xFF);
ESP_LOGI(TAG, "adding info characteristic for motor %d", this->index);
// add callback
this->bleInfoCharacteristic->setCallbacks(new CustomBLEMotorInfoCallback(index, this));
};
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}

View File

@ -2,6 +2,7 @@
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <EEPROM.h>
#include <WiFi.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
@ -50,14 +51,7 @@ char *motorControlCharacteristicUUIDs[] = {
};
// BLE characteristic IDs for each motor
char *motorInfoCharacteristicUUIDs[] = {
"9c05490f-cc74-4fd2-8d16-fb228e3f2270",
"6b342a89-086b-4e6c-8c26-c46352e99709",
"6729beea-61c3-4376-a8fb-9f0aab020ed0",
"faf8581b-1085-4b45-980f-5039db39cfbe",
"69999658-9997-4e57-8e07-e14e0faf9b32",
"d02d9c65-df4d-42d5-abef-24f71b612aad",
};
char *motorInfoCharacteristicUUID = "9c05490f-cc74-4fd2-8d16-fb228e3f2270";
// motor movement direction
// -1 = counter clockwise
@ -135,8 +129,7 @@ void motorTask(void *pvParameter) {
vTaskDelay(20);
}
}
m->currentPosition = ongoingStepTarget;
m->updateCurrentPosition(ongoingStepTarget);
}
vTaskDelay(noActionIdleTime);
@ -203,14 +196,16 @@ extern "C" void app_main() {
BLECharacteristic *ctrl = pService->createCharacteristic(
motorControlCharacteristicUUIDs[i],
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
BLECharacteristic *info = pService->createCharacteristic(motorInfoCharacteristicUUIDs[i],
BLECharacteristic::PROPERTY_READ);
// register characteristic and callback methods
m->addControlCharacteristic(ctrl);
m->addInfoCharacteristic(info);
}
// create single state characteristic
BLECharacteristic *info = pService->createCharacteristic(motorInfoCharacteristicUUID,
BLECharacteristic::PROPERTY_READ);
info->setCallbacks(new CustomBLEMotorInfoCallback(motors));
pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
@ -221,16 +216,17 @@ extern "C" void app_main() {
pServer->setCallbacks(new CustomBLEServerCallback());
// setup serial COMs
// Serial.begin(115200);
// Setup on device memory
// one long 64bit state per motor
EEPROM.begin(8 * 6);
// xTaskCreate(&arduinoTask, "arduino_task", 8192, NULL, 5, NULL);
xTaskCreate(&controlTask, "control_task", 4096, NULL, 3, NULL);
xTaskCreate(&motorTask, "motor_1_task", 4096, (void *)motors[0], 2, NULL);
xTaskCreate(&motorTask, "motor_1_task", 4096, (void *)motors[1], 2, NULL);
xTaskCreate(&motorTask, "motor_1_task", 4096, (void *)motors[2], 2, NULL);
xTaskCreate(&motorTask, "motor_1_task", 4096, (void *)motors[3], 2, NULL);
xTaskCreate(&motorTask, "motor_1_task", 4096, (void *)motors[4], 2, NULL);
xTaskCreate(&motorTask, "motor_1_task", 4096, (void *)motors[5], 2, NULL);
xTaskCreate(&motorTask, "motor_2_task", 4096, (void *)motors[1], 2, NULL);
xTaskCreate(&motorTask, "motor_3_task", 4096, (void *)motors[2], 2, NULL);
xTaskCreate(&motorTask, "motor_4_task", 4096, (void *)motors[3], 2, NULL);
xTaskCreate(&motorTask, "motor_5_task", 4096, (void *)motors[4], 2, NULL);
xTaskCreate(&motorTask, "motor_6_task", 4096, (void *)motors[5], 2, NULL);
}