Giter VIP home page Giter VIP logo

telluiot / thingml Goto Github PK

View Code? Open in Web Editor NEW
102.0 20.0 33.0 317.37 MB

The ThingML modelling language

Home Page: https://github.com/TelluIoT/ThingML

License: Apache License 2.0

Shell 0.14% Java 83.20% Makefile 0.01% C 8.80% C++ 0.60% JavaScript 0.71% HTML 1.56% CSS 0.14% Xtend 4.76% Dockerfile 0.08%
internet-of-things arduino javascript java c modeling-language uml model-driven-development state-machine statechart thingml golang xtext eclipse-modeling

thingml's Introduction

ThingML

The ThingML approach is composed of i) a modeling language, ii) a set of tools and iii) a methodology. The modeling language combines well-proven software modeling constructs for the design and implementation of distributed reactive systems:

  • statecharts and components (aligned with the UML) communicating through asynchronous message passing
  • an imperative platform-independent action language
  • specific constructs targeted at IoT applications.

The ThingML language is supported by a set of tools, which include editors, transformations (e.g. export to UML) and an advanced multi-platform code generation framework, which support multiple target programming languages (C, Java, Javascript). The methodology documents the development processes and tools used by both the IoT service developers and the platform experts.

ThingML is distributed under the Apache 2.0 licence, and has been developed by @ffleurey and @brice-morin of the Networked Systems and Services department of SINTEF in Oslo, Norway, together with a vibrant open-source community. ThingML is now owned by Tellu, but remains open-source.

Issues, bug reports and feature requests should be submitted to the issue tracker on GitHub

Installing ThingML

This section should contain up to date information about getting the latest version of ThingML and getting started with it.

Versions and Distribution

The current recommended version of ThingML is version 2.X.X. Tagged versions are available on the Github release page:

  • A standalone JAR which can be used from the command line: look for the most recent *.jar file on the releases page
  • An eclipse update site to install the ThingML IDE in eclipse: look for the most revent *.zip on the releases page

Version 1.X.X is not maintained and should not be used (maintenance was stopped in Q3 2017). Version 2.X.X introduces a complete rewrite of the parser and editors based on XText. A few syntactical changes make the ThingML programs written for version 1 not compatible with version 2. There are also a few constructs which were evaluated in version 1 and were not re-implemented in version 2 (e.g. groups, streams, etc).

ThingML Command Line Compiler

The ThingML command line compiler is distributed as a standalone JAR. It requires Java 8 or newer. The latest version (*.jar) can be found on the releases pages

The command line tool contains all the code generators and plugins which are part of this repository.

Usage: java -jar ThingML2CLI.jar will provide usage information and a list of options.

ThingML Eclipse-Based IDE

  1. Install "Eclipse IDE for Java and DSL Developers" from the Eclipse website.
  2. Download the most recent update site (*.zip) from the releases pages.
  3. Launch Eclipse
  4. Install the ThingML plugins from the *.zip file: Help -> Install New Software... -> Add... -> Archive...

Usage: Once ThingML plugins are installed, *.thingml files will open with the ThingML editors. Right-click on *.thingml files and use HEADS / ThingML sub-menu to compile a ThingML file. Generated code will be put in a thingml-gen folder at the root of the eclipse project. Remember that only ThingML files containing a configuration can be compiled.

Docker-Based Distribution

Warning: Currently the image on Dockerub is not automatically updated. You should build the image from the Dockerfile to get an up-to-date version of ThingML.

If you have docker, you can use the build container with Eclipse and ThingML at the thingmleditor repository or the thingmleditor docker hub

Sample ThingML programs

The goal of this section is to give a list of example which should work out of the box

Note: over the years and versions, we have collected a lot of different samples and projects made with ThingML. However most of them are not maintained and updated to work with the latest version of ThingML. This might be confusing if you are getting started.

Examples which should be working out of the box:

  • Basic Arduino examples: https://github.com/ffleurey/ThingMLArduinoDemo. The "1.Basics" folder contains a set of simple ThingML/Arduino programs dealing with digital IOs.

  • Multi-platform Breakout game (Arduino, Posix C, Java and Javascript): https://github.com/ffleurey/ThingML-PongTutorial. This example demonstrate how to create platform independent components with ThingML.

  • Arduino <-> Java communication (Serial): https://github.com/ffleurey/ThingML-PressureLogger. This program shows has to create 2 ThingML programs communicating over a serial port. One program is running on an Arduino and collects sensor measurement. The other is a running as a Java program collecting the measurement from the Arduino over the USB/Serial connection and displaying curves. This example is quite minimalistic but should be easy to customize for your own sensor/needs. It shows various features of ThingML like the Serial communication plugin and the possibility of adding Maven dependencies to your ThingML programs.

  • Raspberry Pi GPIOs: https://github.com/ffleurey/ThingML-RPI-Blink A couple of very simple examples showing how to blink an LED on the Raspberry Pi using either C or NodeJS.

Example having known incompatibilities:

Note: Some old samples may be easy to fix but other may use features which have been removed from ThingML.

  • Example from the org.thingml.samples in this repository. This folder contains many samples which were made with various versions of ThingML. It is good to explore to see different things that can be done with ThingML but it is not the place to get working samples when getting started.

  • Tutorials from the HEADS project: https://github.com/HEADS-project/training/tree/master/1.ThingML_Basics. This tutorial is based on ThingML v1.0 which is no longer maintained.

Compiling ThingML Generated Code

The ThingML compiler generate platform specific source code in C, Java, Javascript or Go. This section give short guidelines on how the generated code should be complied and executed.

JAVA / Maven


When compiling to Java, ThingML creates a complete Maven project which is ready to build with mvn clean install and execute with mvn exec:java.

Prerequisites:

  • Make sure you have a proper JDK (a JRE is not sufficient)
  • Install Maven

Using Eclipse:

Configure Eclipse so that it uses the JDK: Window -> Preferences -> Java -> Installed JREs (make sure it points to a JDK)

  • Right click on pom.xml (in thingml-gen/java/your-configuration)
  • Run as -> Maven build...
  • In Goals type: clean install exec:java

If Maven claims it cannot find a pom.xml file, change the base directory in the Run as -> Maven build... window using the Workspace... button, so that it points to thingml-gen/java/your-configuration.

javascript for web browsers


Nothing special. Open the generated index.html file in your System Browser (ideally Chrome or Firefox)

Do not use the default web browser embedded into Eclipse!

Javascript for Node.JS


ThingML creates a standard Node.js package.

Prerequisites:

Using Eclipse:

From this update site: Node.JS - http://www.nodeclipse.org/updates/enide-2015/, install Features included in Enide Studio .Features Set and Nodeclipse Node.js .Features Set 1.0.2.201509250223

  • Right click on package.json (in thingml-gen/nodejs/your-configuration)
  • Run as -> npm install
  • Right click on main.js
  • Run as -> Node Application

Visualize UML Diagrams (PlantUML)


The files generated by the UML generator are text files which uses the PlantUML format. PlantUML will perform the layout and export the diagrams as images.

Prerequisites:

Using Eclipse:

Install PlantUML plugins in Eclipse using this update site: http://hallvard.github.io/plantuml/

  • Window -> Show View -> Other... -> PlantUML

Make sure you have Graphviz installed. It is required by the Eclipse plugin. If you have issues getting PlantUML to work, follow the instructions from http://plantuml.com/eclipse

Posix C


The generated code is a complete C project which include a Makefile.

  • Open a terminal in the filder containing the generated code
  • Compile with make
  • Run with ./your-configuration

Prerequisites:

  • Use a C-friendly OS (such as Linux)
  • Install gcc and make + the libraries you are using.

Note: Virtual box is an option. Ubuntu on Windows 10 works fine as long as there are no graphics/hardware drivers involved.

Arduino C


  • Open the generated file in the Arduino IDE
  • Compile
  • Upload to your board

Prerequisites:

  • Install Arduino IDE
  • Install any Arduino libraries which you are using from your ThingML program

For more information about how to use the Arduino IDE and Arduino boards, have a look at the Arduino documentation.

Go


  • Open a terminal at thingml-gen/go/your-configuration
  • To run the program directly: go run *.go
  • To compile to an executable file: go build *.go

Prerequisites:

For more information about Go package structures, have a look at the Go documentation

Teensy C


Teensy compiler has not be tested for some time. Expect some possible issues when trying it.

Prerequisites:

or

Compile ThingML from the sources

You need Git, Maven, and a proper JDK8+

git clone https://github.com/TelluIoT/ThingML.git
cd ThingML
mvn clean install
cd language
mvn clean install

The command-line interface JAR (containing all you need to compile ThingML files) can be found here:

cd compilers/registry/target
java -jar compilers.registry-2.0.0-SNAPSHOT-jar-with-dependencies.jar
 --- ThingML help ---
Typical usages:
    java -jar your-jar.jar -t <tool> -s <source> [-o <output-dir>] [--options <option>][-d]
Usage: <main class> [options]
  Options:
    --compiler, -c
      Compiler ID (Mandatory unless --tool (-t) is used)
    --create-dir, -d
      Create a new directory named after the configuration for the output
      Default: false
    --help, -h
      Display this message.
      Default: false
    --list-plugins
      Display the list of available plugins
      Default: false
    --options
      additional options for ThingML tools.
    --output, -o
      Optional output directory - by default current directory is used
    --source, -s
      A thingml file to compile (should include at least one configuration)
    --tool, -t
      Tool ID (Mandatory unless --compiler (-c) is used)

Compiler Id must belong to the following list:
 ??     sintefboard     - Generates C++ based in code for Arduino.
 ??     posixmt - Generates C code for Linux or other Posix runtime environments (GCC compiler).
 ??     java    - Generates plain Java code.
 ??     arduino - Generates C/C++ code for Arduino or other AVR microcontrollers (AVR-GCC compiler).
 ??     UML     - Generates UML diagrams in PlantUML
 ??     browser - Generates Javascript code that can run in common Web Browsers.
 ??     nodejsMT        - Generates Multi-Process Javascript code (one nodejs process per instance) for the NodeJS platform.
 ??     nodejs  - Generates Javascript code for the NodeJS platform.
 ??     posix   - Generates C/C++ code for Linux or other Posix runtime environments (GCC compiler).
 ??     debugGUI        - Generates html/js mock-up for other a ThingML external connector

Tool Id must belong to the following list:
 ??     testconfigurationgen    - Generates test configuration for things annnotated with @test "input # output".

🔷 FAQ

🔹 Where can ThingML code run?

Nowhere! Or almost everywhere, from microcontrollers to the cloud!

A ThingML file per se is a design-time specification of the structure (components) and behavior (state machines) of a reactive system. It cannot be directly executed.

A ThingML file can however be compiled (or transformed) to Java/JavaScript/C/Arduino source code, which can in turn be compiled and executed on a platform. Code generated from ThingML has been successfully executed on a large number of platforms: PC Windows/Linux, Raspberry Pi 1, 2 and 3, Intel Edison, Arduino Uno/Mega/Yun/Mini, ESP8266/ESP32, Trinket, Teensy, and probably others.

🔹 How to express this or that in ThingML?

A set of tutorials is available here. The tutorials describe the most common features of ThingML. In addition, an extensive set of tests describes pretty much all the concepts available. Have a look there is you wonder how to express something. Should this information be insufficient, have a look below.

🔹 How is ThingML formalized?

The ThingML language is formalized into an EMF-based metamodel. The textual syntax is formalized as an XText grammar.

🔹 All that code is wonderful, but I need some Science... 📚

ThingML is backed by a set of scientific publications (PDFs can easily be found on e.g. Google Scholar):

  • Model-Based Software Engineering to Tame the IoT Jungle
    Brice Morin, Nicolas Harrand and Franck Fleurey
    In IEEE Software, Special Issue on Internet of Things, 2017.
  • ThingML, A Language and Code Generation Framework for Heterogeneous Targets
    N. Harrand, F. Fleurey, B. Morin and K.E. Husa
    In MODELS’16: ACM/IEEE 19th International Conference on Model Driven Engineering Languages and Systems. Practice and Innovation track. St Malo, France, October 2-7, 2016
  • MDE to Manage Communications with and between Resource-Constrained Systems
    F. Fleurey, B. Morin, A. Solberg and O. Barais.
    In MODELS’11: ACM/IEEE 14th International Conference on Model Driven Engineering Languages and Systems. Wellington, New Zealand, October 2011.

ThingML has also been used together with other approaches:

  • Agile Development of Home Automation System with ThingML
    A. Vasilevskiy, B. Morin, Ø. Haugen and P. Evensen.
    In INDIN’16: 14th IEEE International Conference on Industrial Informatics. Poitiers, France, July 18-21, 2016
  • A Generative Middleware for Heterogeneous and Distributed Services
    B. Morin, F. Fleurey, K.E. Husa, and O. Barais.
    In CBSE’16: 19th International ACM Sigsoft Symposium on Component-Based Software Engineering. Venice, Italy, April 5-8, 2016

🔹 How to embed ThingML in my toolchain?

This currently does not work. Pending a solution to Issue #241

Embed the command-line inteface JAR described previously in this readme in your classpath.

You can also include ThingML as a Maven dependency in your project:

<dependency>
     <groupId>org.thingml</groupId>
     <artifactId>compilers.registry</artifactId>
     <version>2.0.0-SNAPSHOT</version>
</dependency>

...

<repository>
    <id>thingml-snapshot</id>
    <name>thingml-snapshot</name>
    <url>http://maven.thingml.org/thingml-snapshot/</url>
</repository>

<repository>
    <id>thingml-release</id>
    <name>thingml-release</name>
    <url>http://maven.thingml.org/thingml-release/</url>
</repository>

🔹 The code generated by ThingML for Java/JS/C/Arduino does not exactly fit my needs

Rather than being monolithic blobs, compilers are implemented in a modular way around a set of extension points defined in the ThingML Code Generation Framework.

🔹 Why can't I generate Python/Lua/Ruby/you-name-it?

Well, it is up to you to implement a compiler for whatever language that is not supported by default. What are you waiting for?

🔹 How can I programatically process ThingML models?

File myFile = new File("source.thingml");
ThingMLModel myModel = ThingMLCompiler.loadModel(myFile);
//Do something
ThingMLCompiler.saveAsThingML(myModel, "target.thingml");
//or
ThingMLCompiler.saveAsXMI(myModel, "target.xmi");

Protip1: Make sure you have a good understanding of the ThingML metamodel

Protip2: Have a look at the helper functions which simplify some typical treatments

Models saved this way will contain all the imports that the original file refered to in one big file

This feature might currently be broken as we migrated to XText.

🔷 More

ThingML is released under OSI-compliant Apache 2.0 license

thingml's People

Contributors

acartero avatar alexandrerio avatar aliverud avatar barais avatar bitdeli-chef avatar brice-morin avatar docdoc avatar dukeboard avatar ffleurey avatar fleureyf avatar fungiboletus avatar haoshaochi avatar madkira avatar magnustellu avatar nharrand avatar piernov avatar sdalgard avatar skaark42 avatar vassik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thingml's Issues

state machine behaves differently in scala and c/c++

empty transition in c does not trigger shift to another state while it works for scala. The code bellow works for scala, but does not for c and cpp
....
state Started {
transition -> Stopped
}
state Stopped {
}
....

Realization of Port in the language

Currently, a Thing refers to a set of Ports. Each Port is either a RequiredPort or a ProvidedPort. I would suggest having two distinct roles in Thing:

  • providedPorts [0..*] : ProvidedPort
  • requiredPorts [0..*] : RequiredPort

This way, it would avoid the definition of filters in our compilers, since provided and required ports will typically imply different treatments.

Note: If we apply this refactoring, it may not be useful to keep the RequiredPort and ProvidedPort sub-classes.

Std OUT in Arduino

"Maybe we should have annotations which allow generating prints on the serial port or maybe on an LCD screen in some cases."

"Compile-time" properties

Currently all the properties are dynamic but we could have the equivalent of Java final attributes (or scala val) which value would be fixed at compile time. The value of these properties could be used by the code generators in order to optimize the generated code by, for example, substituting the values.

Arrays not properly compiled in Scala when they are not explicitly initialized

property buffer : Byte[16]

The thing declaring this property will be properly compiled, but its instantiation will not compile. When initializing the thing in the configuration (compiled in a scala main), the array is not declared/initialized and it is thus not passed as argument of the constructor, resulting in a compilation error.

workaround until the bug is fixed
property buffer : Byte[16]
set buffer[0] = 0//explicitly initialize the array

Read only property not properly managed in Scala

It should be mapped to a val, to be set when constructing the object in a configuration.

It is currently mapped to a var, which is of course not readonly... even though it will never be re-assigned since ThingML prevent readonly properties to be re-assigned

Problem with RxTx

It seems there is a problem with RxTx on this architecture:
osName=Linux, osProc=amd64

It works fine on Windows and I will make some tests on another version of Linux later on...

if (osName.equals("Linux") && (osProc.equals("x86-64") || osProc.equals("amd64"))) {
System.out.println("Loading native rxtx libs...");
NativeLibUtil.copyFile(Serial4ThingML.class.getClassLoader().getResourceAsStream("nativelib/Linux/x86_64-unknown-linux-gnu/librxtxSerial.so"), "librxtxSerial.so");
System.out.println("Done!");
}

Is it legal to modify the value of parameters passed to a function

We have a test:

 function sendInt(i : Int16) do
        var hundreds : Int8 = i / 100
        i = i - (100 * hundreds)
        var tens : Int8 = i / 10
        i = i - (10 * tens)
        harness!testOut( intToChar(hundreds) )
        harness!testOut( intToChar(tens) )
        harness!testOut( intToChar(i) )
    end

It seems that ThingML allows i to be modified. But It seems the Scala compiler assumes i cannot be modified, where the C compiler allows it.

Should it really be legal in ThingML? Or is it a but in the Scala compiler?

ThingML functions should be declared in generated *.h files

It seems we should (even though I am not expert in C) also declare the ThingML functions in the generated *.h files. In the generated *.c files, it sometimes happen a function is called before it is declared, causing some
"error: conflicting types for ..."
"note: previous implicit declaration of ... was here"

If this is confirmed as an issue by our C expert (Franck), then this would be a blocking issue needing immediate action!

GraphML export with regions

Seems that region are not supported in the GraphML export, as YeD explodes when opening a graphml model containing regions:

y.H.B.B.a: Target node id Start not defined in this graph!
    at y.H.B.B.Y.Ă(Unknown Source)
    at y.H.B.B.Y.ā(Unknown Source)
    at y.H.B.B.Y.Ć(Unknown Source)
    at y.H.B.B.Y.ā(Unknown Source)
    at y.H.B.B.Y.Ą(Unknown Source)
    at y.H.B.B.Y.ā(Unknown Source)
    at y.H.B.B._.ā(Unknown Source)
    at y.H.B.B._.ā(Unknown Source)
    at y.H.B.A$13.ā(Unknown Source)
    at y.H.B.A.ā(Unknown Source)
    at y.H.B.A.ā(Unknown Source)
    at y.H.Q.ā(Unknown Source)
    at B.A.A.B.G.A.F.ā(Unknown Source)
    at B.A.A.B.G.A.F.ā(Unknown Source)
    at B.A.A.B.G.A.D.ā(Unknown Source)
    at y.H.G.ā(Unknown Source)
    at y.B.A.M.ď(Unknown Source)
    at y.B.W.Č(Unknown Source)
    at y.B.W.ā(Unknown Source)
    at y.B.W.ă(Unknown Source)
    at B.A.A.B.Q.Ă(Unknown Source)
    at B.A.A.B.Q.ā(Unknown Source)
    at B.A.A.J.A.ā(Unknown Source)
    at B.A.A.J.A.ā(Unknown Source)
    at B.A.A.J.D.ă(Unknown Source)
    at B.A.A.J.D.Ă(Unknown Source)
    at B.A.A.B$5.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:688)
    at java.awt.EventQueue$3.run(EventQueue.java:686)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Maven release

Refactor the set of projects so that it is easy (as easy as it could be) to release using Maven.

ThingML merger, derived properties

The derived properties on the metamodel significantly helps the implementation of the compilers. However, they are sometimes misleading. For example. calling an opposite property on an element of an allXXXX derived properties still points to the former container object where this element was declared (eg, a fragment).

However, since our different compilers tend to "merge" the ThingML during the compilation process (the C, Scala, etc source code does not contain fragments anymore).

I think the implementation of our compilers would benefit from working on a merged ThingML model.

Maybe a task for Seb? ;-)

Direction on ports

We should have two type of ports to distinguish between required and provided. Maybe we should have "optional" on required ports.

Support for advanced data type

Does ThingML intends to support composite data types and collections? So far, these important concepts are not supported.

Event consumption in Region/Composite

We must clarify how events are consumed in Region and in Composite.

For region running in parallel, I think the consuption of an event by a transition should NOT impact the other // regions. However, I think the consumption of an event by an outgoing transition of a sub-state should (recursively) prevent the composite and siblings to consume this event.

Do you agree?

Once we agree on a given semantics, this should be made crystal clear on the wiki (www.ThingML.net) and strictly ensured/tested by our different execution engine: Scala, Arduino, C (currently)

Default values on properties

It would be useful to have initialization on properties definition. I am thinking of making it mandatory (like in scala).

concept of internal communication wanted!

It seems like we need something that allows passing and receiving messages internally. It is possible do it by defining two ports and connecting them together. It looks quite complex and cluttering a thing. We do not use these ports for communication with other things so we should not expose them publicly. Binding these ports looks redundant and we usually forget this.

We suggest having sort of 'trigger' concept which acts as a couple of ports connected together by default. We should be able to generate more efficient code for the internal communication.

Example:

Expected

thing X includes Xmessages {

    trigger trigger_name message_name;

    statechart behavior init Start {
        ...
        state Start{
          on entry do
            print "Srating...\n"
            b = getSomethig()
            trigger_name!message_name(b)
          end

          transition->Something
          event e : trigger_name?message_name
          .....
        }
       ......
    }
}

Actual (current workaround)

thing X includes Xmessages {
    provided port sendportinternal {
           sends message_name
    }
   required port receiveportinternal {
           receives message_name
    }

    statechart behavior init Start {
        ...
        state Start{
          on entry do
            print "Srating...\n"
            b = getSomethig()
            sendportinternal!message_name(b)
          end

          transition->Something
          event e : receiveportinternal?message_name
          .....
        }
       ......
    }
}
configuration Some {
    instance x:X
    connector x.receiveportinternal => x.sendportinternal // we usually forget this
}

Note:
Franck you can reassign to anyone you want if you think this feature makes sense )))

Typing in ThingML

Is the following code valid?

    function charToInt(c : Char) : Int8 do
        return c - 48
    end

    function intToChar(i : Int8) : Char do
        if ( i > -1 and i < 10) return i + 48
        return -1 // Error
    end     

It seems we are doing some numerical algebra mixing numbers and char... While it is no problem for the C compiler (everything is allowed in C...), it of course generate a compilation error in Scala. Though we will probably not develop a complex type system in ThingML, I think this kind of hack should not be allowed in ThingML i.e. it should be an error reflected at the ThingML level.

Arduino compiler seems broken

When trying to compile the blink sample, I get the following error (when compiling the resulting code in the Arduino IDE):
BlinkArduino:12: error: previous declaration of 'void LedUC_LedImpl_OnEntry(int, LedUC_Instance*)' with 'C++' linkage
BlinkArduino:106: error: conflicts with new declaration with 'C' linkage

Double not supported in the arduino compiler

It seems Double is not support by the Arduino compiler.

The following ThingML code:
message report_rotation(t : Double)//report the angle in radians

Compiles to the following Arduino code:
// Enqueue of messages SensorsDisplay::RemoteControl::report_rotation
void enqueue_SensorsDisplay_send_RemoteControl_report_rotation(struct SensorsDisplay_Instance *_instance, double t){
if ( fifo_byte_available() > 8 ) {

_fifo_enqueue( (19 >> 8) & 0xFF );
_fifo_enqueue( 19 & 0xFF );

// ID of the source instance
_fifo_enqueue( (_instance->id >> 8) & 0xFF );
_fifo_enqueue( _instance->id & 0xFF );

// parameter t
_fifo_enqueue( (t>>24) & 0xFF );//error: invalid operands of types 'double' and 'int' to binary 'operator>>
_fifo_enqueue( (t>>16) & 0xFF );//error: invalid operands of types 'double' and 'int' to binary 'operator>>
_fifo_enqueue( (t>>8) & 0xFF );//error: invalid operands of types 'double' and 'int' to binary 'operator>>
_fifo_enqueue( t & 0xFF );//error: invalid operands of types 'double' and 'int' to binary 'operator>>

}
}

Serial in Arduino 1.0.1

It seems Arduino has changed quite a lot between 0022 and 1.0.1 regarding the way the deal with serial communication... See http://arduino.cc/en/Main/ReleaseNotes

The same ThingML program (using Serial communication on Arduino) compiled with Arduino 0022 and 1.0.1 provides very different results when reading bytes from RxTx on the Java side. (However, it seems some good tools like Putty do not really see any difference... so there might be a way to properly configure RxTx).

For now I am sticking with 0022 for my experiments.

create generic callbacks prototype for c and cpp

The definition of the on_error_callback_client callback in MyThing

function on_error_callback_client(msg: String)
        @c_callback "on_error_callback_client"
do
myport!mymessage(msg)
end

generated code in c

void on_error_callback_client(void *_instance, ...){
        va_list arguments;
        va_start(arguments, _instance);
        const char* msg_blabla = va_arg(arguments, char*);
        va_end(arguments);
       MyThing_send_myport_mymessage((MyThing_Instance *) _instance, msg_blabla );
}

C/C++: parameters enqueueing as pointers should be deprecated

Following discussion with Franck, we should deprecate enqueueing of a message parameter as a pointer to this parameter. Even though it can work when the parameter is allocated in the heap (e.g. the ThingML String type is generated as char*) and things are run on the same machine.

Moreover, ports and messages are concepts which may be used to communicate between things on different machines; thus, a pointer does not make sense.

In addition, please consider the following erroneous example in ThingML:

thing fragment Messages {
    message send_bytes(mbytes : Byte[32]);
}

thing Sender includes Messages {
....
        state SBytes {
            on entry do
                var data : Byte[32]
                data[0] = '0'
                data[1] = '1' 
                datasender!send_bytes(data)
            end         
....
        }

and generated code for the 'on entry' block in C

void Sender_send_datasender_send_bytes(struct Sender_Instance *_instance, uint8_t* mbytes);

void Sender_Behavior_OnEntry(int state, struct Sender_Instance *_instance) {
...
case SENDER_BEHAVIOR_SBYTES_STATE:
{
uint8_t data[32];
data[0] = '0';
data[1] = '1';
cout << "Send bytes "<<data[0]<< data[1] << endl;
Sender_send_datasender_send_bytes(_instance, data);
}
break;
...
}

Since the message handling happens asynchronously, and we pass a pointer to a value (mbytes) on the stack, the pointer contents is changed.

C/C++: @abstract "true" does not work

can get it write, on compilation get something like

[java.lang.UNIXProcess@f19d78 ERR] ThingDeSerializer.cpp: In function ‘void f_ThingDeSerializer_forward(ThingDeSerializer_Instance*)’:
[java.lang.UNIXProcess@f19d78 ERR] ThingDeSerializer.cpp:99:6: error: redefinition of ‘void f_ThingDeSerializer_forward(ThingDeSerializer_Instance*)’
[java.lang.UNIXProcess@f19d78 ERR] ThingDeSerializer.cpp:26:6: error: ‘void f_ThingDeSerializer_forward(ThingDeSerializer_Instance*)’ previously defined here

a negative integer value is diserialized as an unsigned int in a message

C and C++ compilers regard an Integer type in ThingML as an unsigned int. Consider the following simple example

import "../../thingml.thingml"


thing fragment DoorWindowMsg{
    //internal messages
    message dw_state(dwstateneg : Integer, dwstatepos : Integer);
}



thing fragment DoorWindow includes DoorWindowMsg {

    provided port dwintsendport {
        sends dw_state
    }

    required port dwintrecport {
        receives dw_state
    }

    statechart behavior init IsClosedOpened {

        state IsClosedOpened {
            on entry do
                print "DoorWindow: finding out the door/window state...\n"
                dwintsendport!dw_state(get_neg(), get_pos())
            end

            transition->Ready
            event e : dwintrecport?dw_state
            action do
                'printf("Received dw_state %d %d\n", '& e.dwstateneg &', '& e.dwstatepos &');'
                'printf("Call directly %d %d \n", '& get_neg() &', '& get_pos() &');'
            end

        }

        state Ready {
            on entry do
                print "DoorWindow: ready ...\n"
            end

        }

    }
}

thing FibaroDoorWindow includes DoorWindow
@c_header "
#include <stdio.h>
"
{

    function get_neg() : Integer do
        return -10
    end


    function get_pos() : Integer do
        return 10
    end
}


configuration SampleTest
  @output_folder "/home/tmp/"
  @debug "true"
  @debug_fifo "true"
  @debug_message_send ".*"
  @debug_message_receive ".*"
{


    instance dw : FibaroDoorWindow

    // Create and connect the test app

    connector dw.dwintrecport => dw.dwintsendport
}

Integer is defined as

datatype Integer    
    @c_type "int"
    @c_byte_size "2"
    @java_type "Short"
    @SenML_type "Double"
    @ros_type "int16";

Actual output:

THINGML: Starting in debug mode...
DoorWindow: finding out the door/window state...
THINGML: -> FibaroDoorWindow_send_dwintsendport_dw_state
THINGML: <- FibaroDoorWindow_handle_dwintrecport_dw_state
Received dw_state 65526 10
Call directly -10 10 
DoorWindow: ready ...

Expected output:

THINGML: Starting in debug mode...
DoorWindow: finding out the door/window state...
THINGML: -> FibaroDoorWindow_send_dwintsendport_dw_state
THINGML: <- FibaroDoorWindow_handle_dwintrecport_dw_state
Received dw_state -10 10
Call directly -10 10 
DoorWindow: ready ...

Note:
I believe the error is here

dispatch_FibaroDoorWindow_send_dwintsendport_dw_state((struct FibaroDoorWindow_Instance*)instance_by_id((mbuf[0] << 8) + mbuf[1]) /* instance */,
(mbuf[2]<<8) + mbuf[3] /* dwstateneg */ ,
(mbuf[4]<<8) + mbuf[5] /* dwstatepos */ );

Generated Scala code is unpractical (e.g. on Android)

The generated Scala code (and any Scala code in general) is a pain to run on Android, as it produces way too large jar files. We'll replace the Scala compiler with a Kotlin compiler, able to generate JVM code with a very contained overhead, and also able to generate JavaScript, so that we can cover more platforms.

String parameters produce compilation error in Arduino

When using the LCD_screen, the compilation of:

required port Display
    {
        sends initDisplay, refreshDisplay, setDisplay
  // with initDisplay defined as: message initDisplay (id : UInt8, title : String, unit : String, initValue : Integer, minValue : Integer, maxValue : Integer);
    }

produces compilation error in the generated Arduino code:

// parameter title
ptr_union_t __ptrunion_title; //here is the faulty line
__ptrunion_title.pointer = (void*)title;
_fifo_enqueue( __ptrunion_title.buffer[0] );
_fifo_enqueue( __ptrunion_title.buffer[1] );

the error says:

BlinkArduino.cpp: In function 'void enqueue_Meteo_send_Display_initDisplay(Meteo_Instance*, uint8_t, char*, char*, int, int, int)':
BlinkArduino:1608: error: 'ptr_union_t' was not declared in this scope

Note that it works when we add the @sync_send "true" annotation (which is probably better, but still, it should work without that annotation).

Annotations to customize generated Makefile

We should be able to customize the generated Makefile, typically when we wrap existing libraries. For example, the Makefile below integrates a MongoDB component. I had to manually insert 3 elements: -lmongoc, -lbson and -DMONGO_HAVE_STDINT=1

CC = cc
LIBS = -lpthread -lmongoc -lbson 
CFLAGS = -O -w
SRCS = SerialProxy.c ClockTimer.c LinuxSerial.c MessageSerializer.c WeatherStation.c LinuxClock.c MessageDeserializer.c LinuxDB.c RaspiNode.c runtime.c
OBJS = SerialProxy.o ClockTimer.o LinuxSerial.o MessageSerializer.o WeatherStation.o LinuxClock.o MessageDeserializer.o LinuxDB.o RaspiNode.o runtime.o

all : RaspiNode

.c.o :
    ${CC} ${CFLAGS} -c $< -DMONGO_HAVE_STDINT=1

RaspiNode : $(OBJS)
    $(CC) -o $@ $(OBJS) $(LIBS) -lm

clean:
    rm -f *.o *~ RaspiNode

thing fragments defined in separate files and included one by one are not compiled

Consider the following three files:

testA.thingml

import "../../thingml.thingml"

thing fragment A {

    function a() do
        print "a()\n"
    end
}

testB.thingml

import "../../thingml.thingml"
import "testA.thingml"


thing fragment B includes A {

    function b() do
        print "b()\n"
        a()
    end
}

testC.thingml

import "../../thingml.thingml"
import "testB.thingml"

thing fragment C includes B {

    function c() do
        print "c()\n"
        b()
        a()
    end
}

configuration testSeveralFiles {

 instance c : C
}

The thing C cannot call a() from A. On attempt to compile, a NULL pointer exception throws...

Problem with RxTx

It seems there is a problem with RxTx on this architecture:
osName=Linux, osProc=amd64

It works fine on Windows 7 (64) and I will make some tests on another version of Linux later on...

if (osName.equals("Linux") && (osProc.equals("x86-64") || osProc.equals("amd64"))) {//amd64 was missing
System.out.println("Loading native rxtx libs...");
NativeLibUtil.copyFile(Serial4ThingML.class.getClassLoader().getResourceAsStream("nativelib/Linux/x86_64-unknown-linux-gnu/librxtxSerial.so"), "librxtxSerial.so");
System.out.println("Done!");
}

it copies the so file at the root of the project, but then it raises an exception Caused by: java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path

It seems the so file is not copied to the right place... (or maybe it's not the right one)

I am using the RxTx facilities provided by https://github.com/dukeboard/kevoree-extra/tree/master/org.kevoree.extra.osgi.rxtx

Strategy to deal with multiple target languages?

What is the advised strategy to deal with multiple target languages? Currenly ThingML compiles to C, Scala, etc. ThingML allows to define extern expressions (eg, by directly writing some C, when needed eg, for system calls). It's however quite a pain to duplicate all the models where extern statements are involved (eg, to change "millis()" by "System.currentTimeMillis()"). This goes against the MDE practices ThingML advocates... ;-)

Documentation on ThingML annotations

The compilers leverage some annotations in order to adjust how the code is generated. These annotations should be properly documented on the Wiki.

Eclipse bundles for dropins have unresolved deps

The ANTLR plugin should be bundled with the parse to avoid having to install EMFText runtime to use ThingML. Also, as much as possible we should use package deps and not bundle deps. We should also check that all packages are properly exported (at least the CharacterEscaper of the parser is not).

error statement in Arduino compiler

The error statement (the equivalent of System.err.print in Java) is:
1/ not supported in the Arduino compiler (which is not so problematic), and
2/ potentially leads to compilation errors in the resulting code (which is blocking)

For example, the following ThingML code:
if (index == MAX_PACKET_SIZE) do
error("BUFFER OVERFLOW: " + b + " has been ignored. Current index = " + index)
end

compiles to:
if(_instance->PacketManager_index_var == _instance->PacketManager_MAX_PACKET_SIZE_var) {
// ERROR: ("BUFFER OVERFLOW: " + b + " has been ignored. Current index = " + _instance->PacketManager_index_var)}

There should be a \n at the end of the ERROR statement so that the if statement could properly be closed (the closing brace is commented in the generated code

Local variable not changeable

It seems that local variables are not changeable:

readonly var status : Integer = 0

or

var status : Integer = 0 //should be changeable

will result in myLocalVariable.isChangeable == false

BIG_ENDIAN and LITTLE_ENDIAN, Signed and Unsigned

It seems the low-level encoding of datatypes (BIG_ENDIAN, LITTLE_ENDIAN) is not uniform. Globally, it seems we favor BIG_ENDIAN (which is BTW the default encoding for Java). It works OK when we exchange data between Arduino and Scala. But the CoAP generated servers seems to use LITTLE_ENDIAN....

The CoAP compiler should be updated.

Also, we should think about how signed/unsigned C types map to Java types

Scala code does not ensure FIFO order on connectors

It seems messages are sometimes inverted when going through a connector. This is probably due a misalignment between the SMaC framework and ThingML, when it comes to the semantics of ports and connector. In ThingML ports can produce AND receive messages, not in SMaC, where we have to duplicate ports and connectors, which might probably mess up the whole thing.

I will try to align the SMaC framework with ThingML, since it is only use there.

Anyway, the Scala compiler will soon be deprecated and replaced.

Check consistency of compilers

Related to Issue #33, we should have automated tests to ensure the consistency of the different compilers (not just for auto-tranistions) but for all the concepts defined in ThingML

C/C++: a local array in functions is returned as a pointer

Consider the following code in ThingML

function escape() : Byte[34]
do
    var escaped : Byte[34]
    escaped[0] = 0
    return escaped
end

and C generated code

uint8_t* f_Sender_escape(struct Sender_Instance *_instance) {
{
uint8_t escaped[34];
escaped[0] = 0;
return escaped;
}
}

Pointer to a local array is returned. Should never happen....

I would rather prefer dynamic allocation, but still not quite clear where to free this memory block...see below

uint8_t* f_Sender_escape(struct Sender_Instance *_instance) {
{
uint8_t* escaped = (uint8_t*) malloc(sizeof(uint8_t)*34);
escaped[0] = 0;
return escaped;
}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.