Skip to content
This repository was archived by the owner on Jul 25, 2022. It is now read-only.

Commit b1ecd92

Browse files
authored
Merge pull request #5 from LukasPoque/add_broker_feature
Add broker feature
2 parents 9316e55 + fba8593 commit b1ecd92

30 files changed

+2126
-285
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 0.4.0
2+
3+
Add S3I-Broker functionality:
4+
- S3I-B-Messages classes (Message, UserMessage, ServiceMessage (ServiceRequest, ServiceReply), AttributeValueMessage (GetValueRequest, GetValueReply))
5+
- Basic interfaces for the Broker communication (BrokerInterface, ActiveBrokerInterface, PassiveBrokerInterface):
6+
- ActiveBrokerInterface for interfaces that inform you whenever a new message is available
7+
- PassiveBrokerInterface for interfaces where you need to explicitly ask if there are new messages
8+
- An implementation of the ActiveBrokerInterface using the AMQP protocol (not usable for web)
9+
- An implementation of the ActiveBrokerInterface using the REST API of the broker
10+
111
## 0.3.0
212

313
Add linting rules and fulfill them.

README.md

+141-29
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,13 @@ If you are not familiar with the S³I concepts, please read the
3636

3737
For further information see the [KWH Glossar](https://www.kwh40.de/glossar/) and the other [Standpunkte](https://www.kwh40.de/veroffentlichungen/).
3838

39+
## Contributing
40+
41+
PRs are always welcome, check [CONTRIBUTING.md](https://github.com/LukasPoque/s3i_flutter/blob/master/CONTRIBUTING.md) for more info.
42+
3943
## Installing
4044

41-
Please see [Pub.dev](https://pub.dev/packages/s3i_flutter/install) for instructions how to install this package to your flutter app.
45+
Please see [pub.dev](https://pub.dev/packages/s3i_flutter/install) for instructions how to install this package to your flutter app.
4246

4347
If you like this package, consider supporting it by giving a star on [GitHub](https://github.com/LukasPoque/s3i_flutter) and
4448
a like on [pub.dev](https://pub.dev/packages/s3i_flutter) :heart:
@@ -47,15 +51,20 @@ a like on [pub.dev](https://pub.dev/packages/s3i_flutter) :heart:
4751

4852
For a basic example application see the [example](https://github.com/LukasPoque/s3i_flutter/tree/master/example).
4953

54+
Use the [documentation](https://pub.dev/documentation/s3i_flutter/latest/s3i_flutter/s3i_flutter-library.html) of this package for
55+
explicit information about every public method or class.
56+
5057
### Setup authentication
5158

52-
First you need to create a `ClientIdentity` used by your app. Please contact the [KWH4.0](https://www.kwh40.de/kontakt/) to get an app specific client.
59+
First you need to create a `ClientIdentity` used by your app. Please contact the [KWH4.0](https://www.kwh40.de/kontakt/) to get an app
60+
specific client. If you need special client settings like redirect urls (e.g. for the use of the S3I-OAuthProxy) please include this in your
61+
request.
5362
```dart
5463
final clientIdentity = ClientIdentity(<CLIENT-ID>, <CLIENT-SECRET>);
5564
```
5665

5766
Now you can pass this to an `AuthenticationManager` of your choice.
58-
See [here](https://github.com/LukasPoque/s3i_flutter#auth) for a list of some implementations.
67+
See [here](https://github.com/LukasPoque/s3i_flutter#Auth) for a list of some implementations.
5968
In this example we use the `OAuthProxyFlow`. You can specify some scopes to add specific claims in your token.
6069
```dart
6170
final authManager = OAuthProxyFlow(clientIdentity,
@@ -64,24 +73,27 @@ final authManager = OAuthProxyFlow(clientIdentity,
6473
scopes: ["group", "offline_access"]);
6574
```
6675

67-
Last but not least you should use this `AuthenticationManager`-Instance to create a `S3ICore`-Instance.
68-
```dart
69-
final s3i = S3ICore(authManager);
70-
```
71-
7276
If you want to assure that the user is authenticated before going on with other requests
73-
you could trigger the auth process explicit by calling the `login()` function:
77+
you could trigger the auth process explicit by calling the `getAccessToken()` function:
7478
````dart
7579
try {
76-
await s3i.login();
80+
await authManager.getAccessToken();
7781
} on S3IException catch (e) {
7882
debugPrint("Auth failed: " + e.toString());
7983
}
8084
````
8185

82-
If the `S3ICore`-Instance is ready to use you can now receive and update information from the S3I-Services.
86+
### Use the S3I-Directory
87+
88+
If you want to access the S3I-Directory, use the previous constructed `AuthenticationManager`-Instance to create a `S3ICore`-Instance.
89+
```dart
90+
final s3i = S3ICore(authManager);
91+
```
8392

84-
### Get data from the directory
93+
If the `S3ICore`-Instance is ready to use you can now receive and update information from the S3I-Directory (This is subject of
94+
a change in the next releases pls. consider this in your structure).
95+
96+
#### Get data from the directory
8597

8698
To get data about a specific thing you can simply call `getThing()` on your `S3ICore`-Instance.
8799
If you don't need the whole thing it's recommended to use a `FieldQuery` so you only receive a part of the entry
@@ -105,43 +117,137 @@ try {
105117

106118
TODO: add search example
107119

108-
### Update data in the directory
120+
#### Update data in the directory
109121

110122
To update data in the directory it's recommended to request the target before changing it.
111123
This is not needed, because all data classes cloud be created without a version from the cloud but since this package doesn't support `PATCH` requests,
112124
using only local data could lead much more likely to unintentionally overwriting of values.
113125

114126
To update an entry in the directory simply use the `putThing()` or `putPolicy()` method with the locally modified object:
115127
```dart
116-
policyEntry.insertObserver(PolicySubject("nginx:test_observer"));
128+
policyEntry.insertObserver(PolicySubject("nginx:new_test_observer"));
117129
try {
118130
await s3i.putPolicy(policyEntry);
119131
} on S3IException catch (e) {
120132
debugPrint("Update Policy failed: " + e.toString());
121133
}
122134
```
123135

124-
### Send and receive messages via S3I-Broker
136+
### Use the S3I-Broker
125137

126-
TODO: ...
138+
In order to send and receive messages via S3I-Broker you need an implementation of a `BrokerInterface`.
139+
See [here](https://github.com/LukasPoque/s3i_flutter#Broker) for a list of implementations and some background information.
140+
In this example we use an `ActiveBrokerInterface`, because it notifies us if new messages are available. If you are targeting web as a platform too,
141+
use the `getActiveBrokerDefaultConnector` function. This function returns either an AMQPConnector (if your app is not running as web-app) or a
142+
RESTConnector. You can pass the different constructor arguments via the args-map.
143+
```dart
144+
// used to determine if the app is running on the web
145+
import 'package:flutter/foundation.dart' show kIsWeb;
146+
147+
static final ActiveBrokerInterface brokerConnector = kIsWeb
148+
? getActiveBrokerDefaultConnector(authManager,
149+
args: {'pollingInterval': const Duration(milliseconds: 500)})
150+
: getActiveBrokerDefaultConnector(authManager);
151+
```
152+
153+
Now you can register for different events of the brokerConnector. You can even register multiple times for the same event. This is useful
154+
if you want to use the information at different locations in the app (e.g. logging, ui, etc.).
155+
```dart
156+
brokerConnector
157+
..subscribeConsumingFailed((String endpoint, Exception error) {
158+
print('Error on connection $endpoint: $error');
159+
})
160+
..subscribeSendMessageFailed((Message msg, Exception error) {
161+
print('Error while sending message (${msg.identifier}) $error');
162+
})
163+
..subscribeSendMessageSucceeded((Message msg) {
164+
print('Message with id ${msg.identifier} sent');
165+
})
166+
```
167+
168+
#### Receive messages
169+
170+
To receive messages and working with them in your app it's a good idea to register callback for the receiving functions of the brokerConnector.
171+
In this example we're only interested in `ServiceReply`s:
172+
```dart
173+
brokerConnector.subscribeServiceReplyReceived((ServiceReply msg) {
174+
print('Message with id ${msg.identifier} received');
175+
});
176+
```
177+
178+
If all callback you're interested in are registered it's time to start consuming on one (or multiple) queues on the S3I-Broker.
179+
For that simply call `startConsuming`. If you don't want any open connections left when your app closes, call `stopConsuming` with the same endpoint
180+
in your dispose method.
181+
```dart
182+
final String ownEndpoint = '<YOUR ENDPOINT ID>';
183+
brokerConnector.startConsuming(ownEndpoint);
184+
//...
185+
// dispose() or equivalent method
186+
brokerConnector.stopConsuming(ownEndpoint);
187+
```
188+
189+
#### Send messages
190+
191+
To send messages to other things you need to construct a message first. Then you can simply call `sendMessage` with the message and all receiver
192+
endpoints on your broker instance.
193+
```dart
194+
static final request = ServiceRequest(
195+
receivers: <String>{'<SERVICE ID>'},
196+
sender: '<YOUR CLIENT ID>',
197+
replyToEndpoint: '<YOUR ENDPOINT ID>',
198+
serviceType: '<FML40 SERVICE TYPE>',
199+
parameters: <String, dynamic>{<NEEDED PARAMETERS MAP>});
200+
201+
brokerConnector.sendMessage(requestMsg, <String>{'<SERVICE ENDPOINT>'});
202+
```
127203

128204
## Project Structure
129205

130-
TODO: s3i core / entry
206+
The package is divided in domain specific folders.
207+
208+
TODO: ...
131209

132-
### directory
210+
### Auth
133211

134-
### auth
212+
The `auth` folder includes classes which are used to authenticate an user/client in the S3I and could provide valid token to
213+
the other parts of this package where they are used. The folder includes classes for `AccessToken` and `RefreshToken` too.
135214

136-
The `auth` folder includes classes which are used to authenticate a user/client in the S3I.
215+
Currently only the following `AuthenticationManager` implementations are available:
216+
- `OAuthProxyFlow`: This implementation uses the S3I-OAuthProxy to obtain an access and refresh token.
217+
But it doesn't refreshes the tokens automatically, only only if `getAccessToken` is called and the previous token is expired.
137218

138-
The `S3ICore` needs a valid instance of a `AuthenticationManager` to work.
219+
### Broker
139220

140-
Currently there is only one implementation available: `OAuthProxyFlow`.
141-
This implementation of the `AuthenticationManager` uses the S3I-OAuthProxy to obtain an access and refresh token.
142-
But it doesn't refreshes the tokens automatically, only only if `getAccessToken` is called and the `accessToken` is expired.
221+
The `broker` folder includes data classes for the different messages specified in the S3I-B-Protocol and different implementations
222+
of the `BrokerInterface` for communication with the S3I-Broker.
143223

144-
### policy
224+
There are two different approaches to receive messages from the Broker. An `ActiveBrokerInterface` is for interfaces that inform you
225+
whenever a new message is available. A `PassiveBrokerInterface` is for interfaces where you need to explicitly ask if there are new
226+
messages.
227+
228+
At the moment, there are only active broker interfaces implemented:
229+
- `BrokerAmqpConnector`: uses the native communication protocol of the S3i-Broker: AMQP. This is not available for the *web* platform.
230+
- `BrokerRestConnector`: uses the S3I-Broker REST API for sending/receiving of messages.
231+
232+
Currently the following message types are supported:
233+
- `UserMessage`: used for communication between two real users.
234+
- `ServiceMessage`: used to invoke service functions or receive service answers from S3I-Services.
235+
- `GetValueMessage`: used to get a specific value from an other thing.
236+
237+
### Directory
238+
239+
The `directory` folder includes data classes to store and manipulate the entries of a thing from the directory.
240+
241+
The classes are following the *S3I-Directory-Data-Model* with the `Thing` class as their root followed by different chains of
242+
`DirObject`, `Link` and `Value`.
243+
244+
### Exceptions
245+
246+
The `exceptions` folder includes all customized exceptions from this package.
247+
248+
The base class is the `S3IException` which only wraps a normal `Exception` making it easier to catch all specific S3I exceptions.
249+
250+
### Policy
145251

146252
The `policy` folder includes data classes to store and manipulate the policy entries of a thing from the directory OR repository.
147253

@@ -153,10 +259,16 @@ In the S3I-Concept there are two special `PolicyGroup`s which have a specific me
153259
- owner: An owner has READ and WRITE permission to everything (thing:/, policy:/, message:/)
154260
- observer: An observer has only READ permission to the thing part (thing:/)
155261

156-
### broker
262+
### Query
263+
264+
The `query` folder includes the parameters for a (query)request to the S3I-Directory/Repository and the S3I-EventSystem.
157265

158-
### exceptions
266+
Currently the following parameters are used:
267+
- `FieldQuery`: Only the selected fields will be included in the returned json, good for faster and smaller responses.
268+
- `NamespaceQuery`: Limit the query to things in the given namespaces only.
269+
- `OptionQuery`: Used for sorting the responses or enable paging/cursor mechanisms.
270+
- `RQLQuery`: A lightweight query language for the use in URLs (this could be separated to an external package in the future).
159271

160-
### query
272+
### Utils
161273

162-
### utils
274+
The `utils` folder includes useful tools for the whole package. Currently it contains constant json-keys from the S3I-Services.

0 commit comments

Comments
 (0)