Vanuit UML Sketches genereren

Software die niet past in bovenstaande onderwerpen
Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Vanuit UML Sketches genereren

Berichtdoor nicoverduin » 22 Mei 2017, 16:23

Door de jaren heen heb ik meerdere Software pakketten bekeken die volledige ondersteuning konden geven vanuit UML naar source code. Wat ik hiermee bedoel dat ik meer wil dan alleen een code skelet (functie headers en prototypes). Een jaar of 7 terug had ik het pakket van Software Ideas Modeler bekeken. Toen was het nog heel instabiel maar had wel veel potentie. Vorig jaar weer eens een nieuwe versie bekeken en inmiddels een licentie gekocht. Je kan als gebruiker allerlei filters en templates maken waardoor je het zodanig op kan zetten dat ALLE code uit de UML modellen komen. Reverse engineering (dus terug van de code naar de UML) werkt nog deels. Kwestie van tijd.
Waarom zou je? In de professionele wereld wordt er door de klant verwacht dat de code toekomst bestendig is voor een aantal jaren. Daarvoor wordt documentatie gemaakt. Helaas, documentatie maken en laat staan bijhouden wordt als vervelend ervaren en voor je het weet loopt de documentatie achter (en uit de pas) van de realiteit. Voordeel van een pakket als deze is dat je dus de volledige code kan 'hergenereren' vanuit het model. Bijgaand een voorbeeld van een eenvoudige CO2 sensor meting waarbij de PPM (parts per million) een relais aanschakelt als deze onder een drempel waarde komt. continu wordt de ppm tevens op een display getoond.

de context is als volgt :
Afbeelding

Door op de use case de klikken krijg ik mijn klasse diagram:
Afbeelding

Alle componenten worden gedocumenteerd in de verschillende objecten. Ook de specifieke code voor een bepaalde operatie binnen een klasse. De sketch (bij mij is dat een .cpp file vanwege Eclipse)
cpp code
/**
* Project CO2_Sensor
* @file CO2_Sensor.cpp
* @sketch name CO2_Sensor
* @diagram SysteemOverzicht
* @author Nico Verduin
* @date generated 22-5-2017 16:10:15
*/

#include <Arduino.h>
#include "LiquidCrystal_I2C.h"
#include "SystemParameters.h"
#include "ProcessSensor.h"

//
// global variables
//
uint32_t timer_1 = 0; // Timer for flipping led
LiquidCrystal_I2C lcd(0x27,COLUMNS,ROWS); // Creatie van lcd object

/**
* @name setup
* @returns void
*/
void setup()
{
pinMode(RELAIS_PIN, OUTPUT);
digitalWrite(RELAIS_PIN, LOW);
}

/**
* @name loop
* @returns void
*/
void loop()
{

}


De enumeratie :
cpp code
#ifndef SYSTEMPARAMETERS_H
#define SYSTEMPARAMETERS_H
/**
* Project CO2_Sensor
* @file SystemParameters.h
* @enum SystemParameters
* @diagram SysteemOverzicht
* @author Nico Verduin
* @date generated 22-5-2017 16:10:15
* Enumeratie van alle systeem parameters die door het programma gebruikt worden. Na deze aangepast te hebben kan er een source code hergeneratie plaatsvinden en daarna de compilatie en flash.
*/


enum SystemParameters {
SENSOR_PIN = A0, // Aansluiting van de sensor op de analog ingang
RELAIS_PIN = 8, // Aansluiting van het relais op de Arduino.
OPSTART_TIJD = 180000UL, // De CO2 sensor heeft 3 minuten opstart tijd nodig alvorens een correcte meting te kunnen afgeven
PPM_DREMPEL = 450, // PPM_DREMPEL een waarde waarop het systeem op zal reageren
COLUMNS = 16, // Aantal kolommen op LCD display
ROWS = 2 // Aantal Regels op display

};
#endif


De ProcessSensor.h
cpp code
#ifndef PROCESSSENSOR_H
#define PROCESSSENSOR_H
/**
* Project CO2_Sensor
* @file ProcessSensor.h
* @class ProcessSensor
* @diagram SysteemOverzicht
* @author Nico Verduin
* @date generated 22-5-2017 16:10:15
*
*/

#include <Arduino.h>
#include "SystemParameters.h"

class ProcessSensor
{
private:
int16_t _sensorValue; // signed integer waarde van de analoge lezing van de sensor.

bool _sensorOperable; // Geeft aan of de sensor voorbij de opstart tijd is. Zie parameter OPSTART_TIJD

public:
ProcessSensor ();
bool IsReady ();
int16_t leesSensor (uint8_t sensorPin);
int16_t Get_sensorvalue ();

};
#endif


en ProcessSensor.cpp
cpp code
/**
* Project CO2_Sensor
* @file ProcessSensor.cpp
* @class ProcessSensor
* @diagram SysteemOverzicht
* @author Nico Verduin
* @date generated 22-5-2017 16:10:15
*
*/

#include "Arduino.h"
#include "SystemParameters.h"
#include "ProcessSensor.h"

/**
* @name ProcessSensor
* Constructor
*/
ProcessSensor::ProcessSensor()
{
//
// initialiseer object
//
_sensorOperable = false;
_sensorValue = -1;
}

/**
* @name IsReady
* @returns bool
* Controleert of de sensor voldoende is opgewarmd. Zo ja wordt er een true teruggegeven. Zo nee dan een false
*/
bool ProcessSensor::IsReady()
{
//
// kijk of de sensor al warm is
//
if (!_sensorOperable) {
//
// nog niet dus controleer of de opwarm tijd voorbij is
//
if (millis() > OPSTART_TIJD){
_sensorOperable = true;
}
}
//
// geef de status terug
//
return _sensorOperable;
}

/**
* @name leesSensor
* @param sensorPin uint8_t
* @returns int16_t
* Leest de sensor uit

*/
int16_t ProcessSensor::leesSensor(uint8_t sensorPin)
{
//
// controleer dat opstart tijd voorbij is
//
if (_sensorOperable) {
_sensorValue = analogRead(sensorPin);
} else {
_sensorValue = -1; // ongeldige waarde
}
return _sensorValue;
}

/**
* @name Get_sensorvalue
* @returns int16_t
* Geeft de laatst gelezen sensorwaarde terug
*/
int16_t ProcessSensor::Get_sensorvalue()
{
return _sensorValue;
}


Ik heb dus zelf geen enkele aanpassing in de sources hoeven maken. Libraries heb ik gepresenteerd als Packages (juiste naam is wel noodzakelijk). EN je moet UML enigzins beheersen. Het is allemaal nog in ontwikkeling maar door alles te kunnen 'hergenereren' houd ik de documentatie consistent met de documentatie. En verder kun je allerlei reports eruit genereren.
Zie verder : https://www.softwareideas.net/

Wordt vervolgt....
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Advertisement

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Vanuit UML Sketches genereren

Berichtdoor Gij Kieken » 22 Mei 2017, 21:11

Mooi zo.
Hoe houd jij dat in gods naam nog allemaal bij , al die verschillend programmeer talen en software pakketten?

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Vanuit UML Sketches genereren

Berichtdoor nicoverduin » 22 Mei 2017, 22:17

Passie, uiterst zelf kritisch, doorzettingsvermogen en fotografisch geheugen
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Vanuit UML Sketches genereren

Berichtdoor Koepel » 23 Mei 2017, 08:21

Dat ziet er mooi uit.

De 'c' en 'c++' is een standaard, dan kan iedereen een stukje code gebruiken.
De 'html' en 'xml' zijn standaarden.
Nu nog een standaard voor zulke programma's ;) zodat je niet vast zit aan een een bedrijf dat zomaar opgekocht of failliet kan gaan of zou kunnen besluiten dat programma stop te zetten.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Vanuit UML Sketches genereren

Berichtdoor nicoverduin » 23 Mei 2017, 08:33

Op dit moment ondersteunt het:
- C/C++
- Action Script
- C#
- Delphi
- Java
- Javascript
- PHP
- Python
- Ruby
- SQLDdl
- TypeScript
- VB6
- VBNet
- Xsd
Uiteindelijk is het allemaal template gestuurd. Je kan dus ook je eigen taaltje maken. Hier een voorbeeld van een class include file voor cpp:
cpp code
<%==SIM:ExplicitLinesOn==%>
<%==SIM:Set:private=private==%>
<%==SIM:Set:protected=protected==%>
<%==SIM:Set:package=public==%>
<%==SIM:Set:public=public==%>
#ifndef <%==SIM:ToUpper(Element.Name)==%>_H<%==SIM:Line==%>
#define <%==SIM:ToUpper(Element.Name)==%>_H<%==SIM:Line==%>
/**<%==SIM:Line==%>
* Project <%==SIM:Project.Name==%><%==SIM:Line==%>
* @file <%==SIM:Element.Name==%>.h<%==SIM:Line==%>
* @class <%==SIM:Element.Name==%><%==SIM:Line==%>
* @diagram <%==SIM:Element.Diagram.Name==%> <%==SIM:Element.Owner.Name==%><%==SIM:Line==%>
* @author <%==SIM:Project.Authors==%><%==SIM:Line==%>
* @date generated <%==SIM:Now==%><%==SIM:Line==%>
<%==SIM:ForEach:Element.DocumentationLines==%>
* <%==SIM:DocumentationLine==%>
<%==SIM:Line==%>

<%==SIM:EndFor==%>
*/<%==SIM:Line==%>
<%==SIM:Line==%>

<%==SIM:ForEach:Element.Relations==%>
<%==SIM:IfNot:Equals(Substring(Relation.ToElement.ID,0,2),"AC")==%>
<%==SIM:If:Equals(Relation.ToElement.Name,"Arduino")==%>
#include <<%==SIM:Relation.ToElement.Name==%>.h><%==SIM:Line==%>
<%==SIM:EndIf==%>
<%==SIM:EndIf==%>
<%==SIM:EndFor==%>

<%==SIM:ForEach:Element.Relations==%>
<%==SIM:IfNot:Equals(Substring(Relation.ToElement.ID,0,2),"AC")==%>
<%==SIM:IfNot:Equals(Relation.ToElement.Name,Element.Name)==%>
<%==SIM:IfNot:Equals(Relation.ToElement.Name,"Arduino")==%>
#include "<%==SIM:Relation.ToElement.Name==%>.h"<%==SIM:Line==%>
<%==SIM:EndIf==%>
<%==SIM:EndIf==%>
<%==SIM:EndIf==%>
<%==SIM:EndFor==%>

<%==SIM:Line==%>
class <%==SIM:Element.Name==%><%==SIM:If:Element.HasSuperClass==%> : <%==SIM:ForEach:Element.OutRelations.FilterByType(generalization)==%> <%==SIM:Relation.Visibility==%> <%==SIM:Relation.To.Name==%><%==SIM:IfNot:IsLastItem==%>, <%==SIM:EndIf==%><%==SIM:EndFor==%><%==SIM:EndIf==%><%==SIM:Line==%>
{<%==SIM:Line==%>
<%==SIM:IfNot:And(Equals(Element.AllAttributes.FilterByVisibility(private).Count,0),Equals(Element.Operations.FilterByVisibility(private).Count,0))==%>
private:<%==SIM:Line==%>
<%==SIM:ForEach:Element.AllAttributes.FilterByVisibility(private)==%>
<%==SIM:If:Attribute.IsStatic==%> static <%==SIM:EndIf==%><%==SIM:Attribute.Type==%> <%==SIM:Attribute.Name==%>; // <%==SIM:Attribute.Documentation==%><%==SIM:Line==%>
<%==SIM:EndFor==%><%==SIM:Line==%>

<%==SIM:ForEach:Element.Operations.FilterByVisibility(private)==%>
<%==SIM:If:Operation.IsStatic==%> static <%==SIM:EndIf==%><%==SIM:If:Operation.IsVirtual==%> virtual <%==SIM:EndIf==%><%==SIM:If:Operation.HasReturnType==%><%==SIM:Operation.ReturnType==%><%==SIM:EndIf==%><%==SIM:IfNot:Operation.HasReturnType==%>void<%==SIM:EndIf==%> <%==SIM:Operation.Name==%> (<%==SIM:ForEach:Operation.Parameters==%><%==SIM:Parameter.Type==%> <%==SIM:Parameter.Name==%><%==SIM:IfNot:IsLastItem==%>, <%==SIM:EndIf==%><%==SIM:EndFor==%>);<%==SIM:Line==%>
<%==SIM:EndFor==%>

<%==SIM:EndIf==%>
<%==SIM:IfNot:And(Equals(Element.AllAttributes.FilterByVisibility(protected).Count,0),Equals(Element.Operations.FilterByVisibility(protected).Count,0))==%>
protected:<%==SIM:Line==%>
<%==SIM:ForEach:Element.AllAttributes.FilterByVisibility(protected)==%>
<%==SIM:If:Attribute.IsStatic==%> static <%==SIM:EndIf==%><%==SIM:Attribute.Type==%> <%==SIM:Attribute.Name==%>;<%==SIM:Line==%>
<%==SIM:EndFor==%>

<%==SIM:ForEach:Element.Operations.FilterByVisibility(protected)==%>
<%==SIM:If:Operation.IsStatic==%> static <%==SIM:EndIf==%><%==SIM:If:Operation.IsVirtual==%> virtual <%==SIM:EndIf==%><%==SIM:If:Operation.HasReturnType==%><%==SIM:Operation.ReturnType==%><%==SIM:EndIf==%><%==SIM:IfNot:Operation.HasReturnType==%>void<%==SIM:EndIf==%> <%==SIM:Operation.Name==%> (<%==SIM:ForEach:Operation.Parameters==%><%==SIM:Parameter.Type==%> <%==SIM:Parameter.Name==%><%==SIM:IfNot:IsLastItem==%>, <%==SIM:EndIf==%><%==SIM:EndFor==%>);<%==SIM:Line==%>
<%==SIM:EndFor==%>

<%==SIM:Line==%>
<%==SIM:EndIf==%>
<%==SIM:IfNot:And(Equals(Element.AllAttributes.FilterByVisibility(internal,public).Count,0),Equals(Element.Operations.FilterByVisibility(internal,public).Count,0))==%>
public:<%==SIM:Line==%>
<%==SIM:ForEach:Element.AllAttributes.FilterByVisibility(internal,public)==%>
<%==SIM:If:Attribute.IsStatic==%> static <%==SIM:EndIf==%><%==SIM:Attribute.Type==%> <%==SIM:Attribute.Name==%><%==SIM:If:Attribute.HasDefaultValue==%> = <%==SIM:Attribute.DefaultValue==%><%==SIM:EndIf==%>;<%==SIM:Line==%>
<%==SIM:EndFor==%>

<%==SIM:ForEach:Element.Operations.FilterByVisibility(internal,public)==%>
<%==SIM:If:Operation.IsStatic==%> static <%==SIM:EndIf==%>
<%==SIM:If:Operation.IsVirtual==%> virtual <%==SIM:EndIf==%>
<%==SIM:If:Operation.HasReturnType==%><%==SIM:Operation.ReturnType==%> <%==SIM:EndIf==%>
<%==SIM:IfNot:Operation.HasReturnType==%>
<%==SIM:If:Operation.HasStereoType(xxxxxx)==%> <%==SIM:EndIf==%>
<%==SIM:If:Operation.HasStereoType(destroy)==%> ~<%==SIM:EndIf==%>
<%==SIM:IfNot:Operation.HasStereoType(create)==%>void <%==SIM:EndIf==%>
<%==SIM:EndIf==%>
<%==SIM:Operation.Name==%> (
<%==SIM:ForEach:Operation.Parameters==%>
<%==SIM:Parameter.Type==%> <%==SIM:Parameter.Name==%><%==SIM:IfNot:IsLastItem==%>, <%==SIM:EndIf==%>
<%==SIM:EndFor==%>);<%==SIM:Line==%>
<%==SIM:EndFor==%>

<%==SIM:Line==%>
<%==SIM:EndIf==%>
};<%==SIM:Line==%>
#endif


Het is ff wennen, maar na een weekje klooien heb ik ze bijna zoals ik ze wil.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Vanuit UML Sketches genereren

Berichtdoor nicoverduin » 23 Mei 2017, 08:46

En je kan ook een andere taal kiezen. Als ik Blink_without_delay zou gebruiken voor VB6. Komt er nu al dit uit:
vb code
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "blink_without_delay"
Attribute VB_Creatable = True
Attribute VB_Exposed = False
Option Explicit
Private mtimer_1 As uint32_t

'Timer for flipping led
Public Property Let timer_1 (value As uint32_t)
mtimer_1 = value
End Property

Public Property Get timer_1 () As uint32_t
timer_1 = mtimer_1
End Property

'Initializes the sketch
Public Function setup () As void

End Function

'Is continuously called from main.cpp. Thus loops forever
Public Function loop () As void

End Function


Terwijl voor de Arduino (alle files ff achter elkaar)
cpp code
#ifndef SYSTEMPARAMETERS_H
#define SYSTEMPARAMETERS_H
/**
* Project blink_without_delay
* @file SystemParameters.h
* @enum SystemParameters
* @diagram SystemDesign
* @author Nico Verduin
* @date generated 23-5-2017 8:51:45
* Enumeratie van alle systeem parameters die door het programma gebruikt worden. Na deze aangepast te hebben kan er een source code hergeneratie plaatsvinden en daarna de compilatie en flash.
*/


enum SystemParameters {
LED_PIN = 13, // Fixed led on D13
TIME_DELAY = 500 // Time between LED change

};
#endif
/**
* Project blink_without_delay
* @file blink_without_delay.ino
* @sketch name blink_without_delay
* @diagram SystemDesign
* @author Nico Verduin
* @date generated 23-5-2017 8:51:45
*
*/

#include <Arduino.h>
#include "SystemParameters.h"

//
// global variables
//
uint32_t timer_1 = 0; // Timer for flipping led

/**
* @name setup
* @returns void
* Initializes the sketch
*/
void setup()
{
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
timer_1 = millis();
}

/**
* @name loop
* @returns void
* Is continuously called from main.cpp. Thus loops forever
*/
void loop()
{
if (millis() - timer_1 > TIME_DELAY){
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
timer_1 = millis();
}
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 340
Geregistreerd: 23 Okt 2016, 20:29

Re: Vanuit UML Sketches genereren

Berichtdoor benvo » 28 Mei 2017, 11:29

Leuk om te zien, temeer dat het onderdeel wat je benoemd CO2 meting een onderdeel moet gaan worden voor mij controller. Beneden of boven een bepaalde waarde wordt dan de CO2 toevoer middels een relais en een magneet klep al of niet aan gezet.


Groet,
Ben.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Vanuit UML Sketches genereren

Berichtdoor nicoverduin » 28 Mei 2017, 19:56

Tja het is een PoC project voor een klant. Kijken of het wat is. Voor mij wordt het een mooie oefencase met UML. Eerst maar eens zien of het wat wordt als ie binnen is.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Terug naar Overige Software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 10 gasten