s3i_flutter 0.5.0
s3i_flutter: ^0.5.0 copied to clipboard

A library that makes it easy to communicate with the S³I (Smart Systems Service Infrastructure of the KWH4.0).

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:s3i_flutter/s3i_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

// used to determine if the app is running on the web
import 'package:flutter/foundation.dart' show kIsWeb;

//TODO: replace with your own client data
// the client used here has no permissions in the s3i unless your personal
// account grants some
final clientIdentity = ClientIdentity("s3i:flutter-example-client",
    secret: "86c0025d-3cb4-4db8-a8d3-4bf30e2e0930");
final String ownEndpoint = 's3ib://s3i:cb420dbc-0d0f-4c57-8cf6-12bdf96b8578';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'S3I Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightGreen,
      ),
      home: MyHomePage(title: 'S3I Flutter Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  // place this instances somewhere else in your application and use a proper
  // state management solution for the things/login state etc.
  static final authManager = OAuthProxyFlow(clientIdentity,
      maxRetryPickup: 500,
      retryWaitingTimeMilliSec: 100,
      openUrlCallback: openUrl, onAuthSuccess: () {
    debugPrint("Auth succeeded");
  }, scopes: ["group", "offline_access"]);
  static final s3i = S3ICore(authManager);

  static final Future<void> Function(Uri) openUrl = (url) async {
    // open the given url in the default browser
    await canLaunch(url.toString())
        ? await launch(url.toString())
        : throw "Could not open the login page" + url.toString();
  };

  /// pass extra information to the REST connector (if we are running on web)
  static final ActiveBrokerInterface brokerConnector = kIsWeb
      ? getActiveBrokerDefaultConnector(authManager,
          args: {'pollingInterval': const Duration(milliseconds: 500)})
      : getActiveBrokerDefaultConnector(authManager)
    // subscribe to events of the active broker interface
    ..subscribeConsumingFailed((endpoint, error) {
      print('Error on connection $endpoint: $error');
    })
    ..subscribeSendMessageFailed((msg, error) {
      print('Error while sending message (${msg.identifier}) $error');
    })
    ..subscribeSendMessageSucceeded((msg) {
      print('Message with id ${msg.identifier} sent');
    })
    ..subscribeServiceReplyReceived((msg) {
      print('Message with id ${msg.identifier} received');
    });

  //id of the vSFL passability service (could be offline)
  static final String serviceId = 's3i:aae1178b-0499-47bf-a7c6-58fa92102e1a';
  static final String serviceEndpoint = 's3ib://$serviceId';

  //create new service request
  static final request = ServiceRequest(
      receivers: <String>{serviceId},
      sender: clientIdentity.id,
      replyToEndpoint: ownEndpoint,
      serviceType: 'fml40::ProvidesPassabilityInformation/calculatePassability',
      parameters: <String, String>{'load': '40', 'moisture': '60'});

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final thingIdInputController = TextEditingController();
  final policyIdInputController = TextEditingController();

  // s3i values
  AccessToken? accessToken;
  Thing? requestedThing;
  PolicyEntry? requestedPolicy;
  ServiceReply? lastReply;

  _MyHomePageState() {
    //connect to service reply a second time to setState
    MyHomePage.brokerConnector.subscribeServiceReplyReceived((msg) {
      setState(() {
        lastReply = msg;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: ListView(
            children: <Widget>[
              _buildAuthArea(),
              Divider(height: 5, thickness: 5),
              _buildThingRequestArea(),
              Divider(height: 5, thickness: 5),
              _buildEditThingArea(),
              Divider(height: 5, thickness: 5),
              _buildPolicyRequestArea(),
              Divider(height: 5, thickness: 5),
              _buildBrokerArea(),
            ],
          ),
        ));
  }

  Widget _buildAuthArea() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          ElevatedButton(
            onPressed: () async {
              // use try/catch and handle the "expected" errors that could be thrown
              try {
                var token = await MyHomePage.s3i.login();
                setState(() {
                  accessToken = token;
                });
              } on S3IException catch (e) {
                debugPrint("Auth failed");
                debugPrint(e.toString());
              }
            },
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text('Login via S³I'),
            ),
          ),
          SizedBox(height: 16),
          SelectableText(accessToken != null ? accessToken!.originalToken : ""),
          SizedBox(height: 8),
          SelectableText(accessToken != null
              ? accessToken!.decodedPayload.toString()
              : ""),
        ],
      ),
    );
  }

  Widget _buildThingRequestArea() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          Row(
            children: [
              Expanded(
                child: TextField(
                  controller: thingIdInputController,
                ),
              ),
              SizedBox(width: 8),
              OutlinedButton(
                  onPressed: () async {
                    try {
                      // requests the given thing id
                      // you need read access to the thing
                      var thing = await MyHomePage.s3i
                          .getThing(thingIdInputController.text);
                      setState(() {
                        requestedThing = thing;
                      });
                    } on S3IException catch (e) {
                      debugPrint("Request Thing failed");
                      debugPrint(e.toString());
                      setState(() {
                        requestedThing = null;
                      });
                    }
                  },
                  child: Text("Request Thing"))
            ],
          ),
          SizedBox(height: 8),
          if (requestedThing != null) _buildThingRep(requestedThing!)
        ],
      ),
    );
  }

  Widget _buildEditThingArea() {
    return requestedThing != null
        ? Padding(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              onPressed: () async {
                try {
                  // adds an fictional feature to the thing which is loaded
                  // you need write access to the thing
                  var newLink = Link("feature");
                  newLink.target = DirObject("s3i_test");
                  // you need to check every nullable value for safe usage!
                  requestedThing!.thingStructure!.links!.add(newLink);
                  await MyHomePage.s3i.putThing(requestedThing!);
                } on S3IException catch (e) {
                  debugPrint("Put Thing failed");
                  debugPrint(e.toString());
                }
              },
              child: Text("Add Feature <s3i_test> to the thing"),
            ),
          )
        : Container();
  }

  Widget _buildPolicyRequestArea() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          Row(
            children: [
              Expanded(
                child: TextField(
                  controller: policyIdInputController,
                ),
              ),
              SizedBox(width: 8),
              OutlinedButton(
                  onPressed: () async {
                    try {
                      // requests the given policy
                      // you need read access to the policy
                      var policy = await MyHomePage.s3i
                          .getPolicy(policyIdInputController.text);
                      setState(() {
                        requestedPolicy = policy;
                      });
                    } on S3IException catch (e) {
                      debugPrint("Request Policy failed");
                      debugPrint(e.toString());
                      setState(() {
                        requestedPolicy = null;
                      });
                    }
                  },
                  child: Text("Request Policy"))
            ],
          ),
          SizedBox(height: 8),
          if (requestedPolicy != null) Text(requestedPolicy.toString())
        ],
      ),
    );
  }

  Widget _buildBrokerArea() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          ElevatedButton(
            onPressed: () async {
              // subscribe to our own queue
              MyHomePage.brokerConnector.startConsuming(ownEndpoint);
            },
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text('Start consuming own endpoint'),
            ),
          ),
          SizedBox(width: 8),
          ElevatedButton(
            onPressed: () async {
              // Unsubscribe to our own queue
              MyHomePage.brokerConnector.stopConsuming(ownEndpoint);
            },
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text('Stop consuming own endpoint'),
            ),
          ),
          SizedBox(width: 8),
          OutlinedButton(
              onPressed: () async {
                //send service request
                MyHomePage.brokerConnector.sendMessage(
                    MyHomePage.request, <String>{MyHomePage.serviceEndpoint});
              },
              child: Text("Send Service-Request to Passability-Service")),
          SizedBox(height: 8),
          if (lastReply != null) Text(lastReply!.toJson().toString()),
        ],
      ),
    );
  }

  @override
  void dispose() {
    thingIdInputController.dispose();
    // Unsubscribe to our own queue, disconnect from the broker
    // this is not necessary
    MyHomePage.brokerConnector.stopConsuming(ownEndpoint);
    super.dispose();
  }
}

Widget _buildThingRep(Thing requestedThing) {
  return Column(
    children: [
      Row(
        children: [
          Text("Name:"),
          SizedBox(width: 8),
          Expanded(
              child: Text(
                  requestedThing.name != null ? requestedThing.name! : "-")),
        ],
      ),
      SizedBox(height: 8),
      Row(
        children: [
          Text("Owned By:"),
          SizedBox(width: 8),
          Expanded(
              child: Text(requestedThing.ownedBy != null
                  ? requestedThing.ownedBy!
                  : "-")),
        ],
      ),
      SizedBox(height: 8),
      Row(
        children: [
          Text("Attributes:"),
          SizedBox(width: 8),
          Expanded(
            child: Text(requestedThing.thingStructure != null
                ? requestedThing.thingStructure!.toString()
                : "-"),
          ),
        ],
      )
    ],
  );
}
1
likes
130
pub points
14%
popularity

Publisher

lukas-poque.dev

A library that makes it easy to communicate with the S³I (Smart Systems Service Infrastructure of the KWH4.0).

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

crypto, dart_amqp, flutter, http, uuid

More

Packages that depend on s3i_flutter