Skip to content

Commit 7d266e8

Browse files
committed
Add ArduinoCloudThing
1 parent 2294fd7 commit 7d266e8

File tree

2 files changed

+241
-0
lines changed

2 files changed

+241
-0
lines changed

src/ArduinoIoTCloudThing.cpp

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*
2+
This file is part of the Arduino_SecureElement library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
12+
/******************************************************************************
13+
* INCLUDE
14+
******************************************************************************/
15+
16+
#include <AIoTC_Config.h>
17+
18+
#ifdef HAS_TCP
19+
20+
#include "ArduinoIoTCloudThing.h"
21+
#include "interfaces/CloudProcess.h"
22+
#include "property/types/CloudWrapperInt.h"
23+
#include "property/types/CloudWrapperUnsignedInt.h"
24+
25+
/******************************************************************************
26+
* CTOR/DTOR
27+
******************************************************************************/
28+
ArduinoCloudThing::ArduinoCloudThing(MessageStream* ms)
29+
: CloudProcess(ms),
30+
_state{State::Init},
31+
_syncAttempt(0, 0),
32+
_propertyContainer(0),
33+
_propertyContainerIndex(0),
34+
_utcOffset(0),
35+
_utcOffsetProperty(nullptr),
36+
_utcOffsetExpireTime(0),
37+
_utcOffsetExpireTimeProperty(nullptr) {
38+
}
39+
40+
/******************************************************************************
41+
* PUBLIC MEMBER FUNCTIONS
42+
******************************************************************************/
43+
44+
void ArduinoCloudThing::begin() {
45+
Property* property;
46+
47+
property = new CloudWrapperInt(_utcOffset);
48+
_utcOffsetProperty = &addPropertyToContainer(getPropertyContainer(),
49+
*property,
50+
"tz_offset",
51+
Permission::ReadWrite, -1);
52+
_utcOffsetProperty->writeOnDemand();
53+
property = new CloudWrapperUnsignedInt(_utcOffsetExpireTime);
54+
_utcOffsetExpireTimeProperty = &addPropertyToContainer(getPropertyContainer(),
55+
*property,
56+
"tz_dst_until",
57+
Permission::ReadWrite, -1);
58+
_utcOffsetExpireTimeProperty->writeOnDemand();
59+
}
60+
61+
void ArduinoCloudThing::update() {
62+
/* Run through the state machine. */
63+
State nextState = _state;
64+
switch (_state) {
65+
case State::Init: nextState = handleInit(); break;
66+
case State::RequestLastValues: nextState = handleRequestLastValues(); break;
67+
case State::Connected: nextState = handleConnected(); break;
68+
case State::Disconnect: nextState = handleDisconnect(); break;
69+
}
70+
71+
/* Handle external events */
72+
switch (_command) {
73+
case LastValuesUpdateCmdId:
74+
if (_state == State::RequestLastValues) {
75+
DEBUG_VERBOSE("CloudThing::%s Thing is synced", __FUNCTION__);
76+
nextState = State::Connected;
77+
}
78+
break;
79+
80+
/* We have received a reset command */
81+
case ResetCmdId:
82+
nextState = State::Init;
83+
break;
84+
85+
default:
86+
break;
87+
}
88+
89+
_command = UnknownCmdId;
90+
_state = nextState;
91+
}
92+
93+
int ArduinoCloudThing::connected() {
94+
return _state > State::Disconnect ? 1 : 0;
95+
}
96+
97+
void ArduinoCloudThing::handleMessage(Message* m) {
98+
_command = UnknownCmdId;
99+
if (m != nullptr) {
100+
_command = m->id;
101+
}
102+
}
103+
104+
ArduinoCloudThing::State ArduinoCloudThing::handleInit() {
105+
_syncAttempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms);
106+
return State::RequestLastValues;
107+
}
108+
109+
ArduinoCloudThing::State ArduinoCloudThing::handleRequestLastValues() {
110+
/* Check whether or not we need to send a new request. */
111+
if (_syncAttempt.isRetry() && !_syncAttempt.isExpired()) {
112+
return State::RequestLastValues;
113+
}
114+
115+
/* Track the number of times a get-last-values request was sent to the cloud.
116+
* If no data is received within a certain number of retry-requests it's a
117+
* better strategy to disconnect and re-establish connection from the ground up.
118+
*/
119+
if (_syncAttempt.getRetryCount() > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) {
120+
return State::Disconnect;
121+
}
122+
123+
_syncAttempt.retry();
124+
125+
/* Send message upstream to inform infrastructure we need to request thing
126+
* last values
127+
*/
128+
DEBUG_VERBOSE("CloudThing::%s not int sync. %d next sync request in %d ms",
129+
__FUNCTION__, _syncAttempt.getRetryCount(), _syncAttempt.getWaitTime());
130+
Message message = { LastValuesBeginCmdId };
131+
deliver(&message);
132+
133+
return State::RequestLastValues;
134+
}
135+
136+
ArduinoCloudThing::State ArduinoCloudThing::handleConnected() {
137+
/* Check if a primitive property wrapper is locally changed.
138+
* This function requires an existing time service which in
139+
* turn requires an established connection. Not having that
140+
* leads to a wrong time set in the time service which inhibits
141+
* the connection from being established due to a wrong data
142+
* in the reconstructed certificate.
143+
*/
144+
updateTimestampOnLocallyChangedProperties(getPropertyContainer());
145+
146+
/* Configure Time service with timezone data:
147+
* _utcOffset [offset + dst]
148+
* _utcOffsetExpireTime [posix timestamp until _utcOffset is valid]
149+
*/
150+
if (_utcOffsetProperty->isDifferentFromCloud() ||
151+
_utcOffsetExpireTimeProperty->isDifferentFromCloud()) {
152+
_utcOffsetProperty->fromCloudToLocal();
153+
_utcOffsetExpireTimeProperty->fromCloudToLocal();
154+
TimeService.setTimeZoneData(_utcOffset, _utcOffsetExpireTime);
155+
}
156+
157+
/* Check if any property needs encoding and send them to the cloud */
158+
Message message = { PropertiesUpdateCmdId };
159+
deliver(&message);
160+
161+
if (getTime() > _utcOffsetExpireTime) {
162+
return State::RequestLastValues;
163+
}
164+
165+
return State::Connected;
166+
}
167+
168+
ArduinoCloudThing::State ArduinoCloudThing::handleDisconnect() {
169+
return State::Disconnect;
170+
}
171+
172+
#endif /* HAS_TCP */

src/ArduinoIoTCloudThing.h

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
This file is part of the Arduino_SecureElement library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
12+
#ifndef ARDUINO_IOT_CLOUD_THING_H
13+
#define ARDUINO_IOT_CLOUD_THING_H
14+
15+
/******************************************************************************
16+
* INCLUDE
17+
******************************************************************************/
18+
19+
#include "interfaces/CloudProcess.h"
20+
#include "utility/time/TimedAttempt.h"
21+
#include "property/PropertyContainer.h"
22+
23+
/******************************************************************************
24+
* CLASS DECLARATION
25+
******************************************************************************/
26+
27+
class ArduinoCloudThing : public CloudProcess {
28+
public:
29+
30+
ArduinoCloudThing(MessageStream *stream);
31+
virtual void update() override;
32+
virtual void handleMessage(Message *m) override;
33+
34+
virtual void begin();
35+
virtual int connected();
36+
37+
inline PropertyContainer &getPropertyContainer() {
38+
return _propertyContainer;
39+
};
40+
inline unsigned int &getPropertyContainerIndex() {
41+
return _propertyContainerIndex;
42+
}
43+
44+
private:
45+
46+
enum class State {
47+
Disconnect,
48+
Init,
49+
RequestLastValues,
50+
Connected,
51+
};
52+
53+
State _state;
54+
CommandId _command;
55+
TimedAttempt _syncAttempt;
56+
PropertyContainer _propertyContainer;
57+
unsigned int _propertyContainerIndex;
58+
int _utcOffset;
59+
Property *_utcOffsetProperty;
60+
unsigned int _utcOffsetExpireTime;
61+
Property *_utcOffsetExpireTimeProperty;
62+
63+
State handleInit();
64+
State handleRequestLastValues();
65+
State handleConnected();
66+
State handleDisconnect();
67+
};
68+
69+
#endif /* ARDUINO_IOT_CLOUD_THING_H */

0 commit comments

Comments
 (0)