Recettes sur Vijeo-designer.
- itasoft
- Mi homme - Mi automate
- Messages : 7152
- Enregistré le : 20 oct. 2015, 10:15
- Localisation : Lyon
- Contact :
Recettes sur Vijeo-designer.
Recettes sur Vijeo-designer.
La question avait été posée sur ce forum à une époque, sans réponse.
Via une communication on reçois le code de la recette à charger.
La question était de comment trouver le n° de la recette d’après son code (étiquette) .
Une des solutions consisterait à copier toutes les étiquettes des recette dans un tableau de String dans l’ordre des n°
puis parcourir ce tableau pour chercher l’étiquette (le code) demandé et le rang nous donnera son n°
L’autre solution consisterait à charger les recettes une par une jusqu’a ce que l’on trouve celle que l’on cherche,
mais c’est beaucoup plus long surtout si c’est la dernière de la liste.
Qu’en pensez vous ?
La question avait été posée sur ce forum à une époque, sans réponse.
Via une communication on reçois le code de la recette à charger.
La question était de comment trouver le n° de la recette d’après son code (étiquette) .
Une des solutions consisterait à copier toutes les étiquettes des recette dans un tableau de String dans l’ordre des n°
puis parcourir ce tableau pour chercher l’étiquette (le code) demandé et le rang nous donnera son n°
L’autre solution consisterait à charger les recettes une par une jusqu’a ce que l’on trouve celle que l’on cherche,
mais c’est beaucoup plus long surtout si c’est la dernière de la liste.
Qu’en pensez vous ?
Automaticien privé (de tout)
itasoft@free.fr
itasoft@free.fr
Re: Recettes sur Vijeo-designer.
hello,
le problème c'est que tu n'as pas accès aux données des recettes sans impacter les champs d'affichage / d'édition.
il faut construire un mapping "numéro (indice) <=> nom" en parallèle et faire la recherche sur cette table (avec mise à jour de la table à chaque modif de nom de recette).
pour comparer les chaînes de caractères rapidement, il faut calculer un code de hachage par chaîne (hashing) --> https://fr.wikipedia.org/wiki/Fonction_de_hachage
c'est jouable, mais ça devient (très) lourd à faire juste avec le java "light" de Vijeo.
@+
le problème c'est que tu n'as pas accès aux données des recettes sans impacter les champs d'affichage / d'édition.
il faut construire un mapping "numéro (indice) <=> nom" en parallèle et faire la recherche sur cette table (avec mise à jour de la table à chaque modif de nom de recette).
pour comparer les chaînes de caractères rapidement, il faut calculer un code de hachage par chaîne (hashing) --> https://fr.wikipedia.org/wiki/Fonction_de_hachage
c'est jouable, mais ça devient (très) lourd à faire juste avec le java "light" de Vijeo.
@+
Re: Recettes sur Vijeo-designer.
Salut Antoine
J'ai eu ce genre de truc à faire sur un afficheur automate Proface série lt300 ou un truc du genre.
Ce qui a été programmé :
Au démarrage de l'afficheur, une fonction qui lit les 500 recettes pour sauvegarder les noms en zone ls.
Cette manip prenait environ 15 secondes.
Sur saisie code barre, on testait la chaîne saisie avec le tableau de noms sans algorithme spécifique.
Ça allait suffisamment vite
Toutes ces phases de prog était programmées dans le code automate intégré......
Pour ton cas, si tu as de la latitude du client:
Je stockerais les recettes en data automate.
Je pense que les fonctions de recherche iraient beaucoup plus vite.
C'est sur qu'il faut un vrai automate.....
J'ai eu ce genre de truc à faire sur un afficheur automate Proface série lt300 ou un truc du genre.
Ce qui a été programmé :
Au démarrage de l'afficheur, une fonction qui lit les 500 recettes pour sauvegarder les noms en zone ls.
Cette manip prenait environ 15 secondes.
Sur saisie code barre, on testait la chaîne saisie avec le tableau de noms sans algorithme spécifique.
Ça allait suffisamment vite
Toutes ces phases de prog était programmées dans le code automate intégré......
Pour ton cas, si tu as de la latitude du client:
Je stockerais les recettes en data automate.
Je pense que les fonctions de recherche iraient beaucoup plus vite.
C'est sur qu'il faut un vrai automate.....
- itasoft
- Mi homme - Mi automate
- Messages : 7152
- Enregistré le : 20 oct. 2015, 10:15
- Localisation : Lyon
- Contact :
Re: Recettes sur Vijeo-designer.
slts,
une des solutions testée:
1) Copier en permanence les noms des étiquettes dans un tableau de DINT (le hashCode)
2) Faire une recherche du code à trouver dans ce tableau, le rang donne le n° de la recette
exemple de script:
//=== Nombre de recettes dans le Groupe de Recettes ====
int RMax=100;
//==Copie des labels dans la table TAB_LABELS==
_RecipeControlDefault.RecipeGroupNumber.write(1);
String label=_RecipeControlDefault.RecipeLabel.getStringValue();
int X=INDEX.getIntValue();INDEX.add(1);
TAB_LABELS[X].write(label.hashCode());
if(X>=RMax){X=0;INDEX.write(0);OKCopy.write(1);}
_RecipeControlDefault.RecipeNumber.write(X+1);
//==Nom de l'Etiquette à chercher dans la table==
label=WLabel.getStringValue();
//== hashCode de l'Etiquette à chercher==
int HCode=label.hashCode();
//==n°recette==
int nr=0;
//==boucle de recherche dans la table des labels==
for (X = 1; X <=RMax; X++)
if (TAB_LABELS[X].getIntValue()==HCode) nr=X;
//== n° de la recette trouvée ou 0 si trouve pas==
NUM_RECETTE.write(nr);
une des solutions testée:
1) Copier en permanence les noms des étiquettes dans un tableau de DINT (le hashCode)
2) Faire une recherche du code à trouver dans ce tableau, le rang donne le n° de la recette
exemple de script:
//=== Nombre de recettes dans le Groupe de Recettes ====
int RMax=100;
//==Copie des labels dans la table TAB_LABELS==
_RecipeControlDefault.RecipeGroupNumber.write(1);
String label=_RecipeControlDefault.RecipeLabel.getStringValue();
int X=INDEX.getIntValue();INDEX.add(1);
TAB_LABELS[X].write(label.hashCode());
if(X>=RMax){X=0;INDEX.write(0);OKCopy.write(1);}
_RecipeControlDefault.RecipeNumber.write(X+1);
//==Nom de l'Etiquette à chercher dans la table==
label=WLabel.getStringValue();
//== hashCode de l'Etiquette à chercher==
int HCode=label.hashCode();
//==n°recette==
int nr=0;
//==boucle de recherche dans la table des labels==
for (X = 1; X <=RMax; X++)
if (TAB_LABELS[X].getIntValue()==HCode) nr=X;
//== n° de la recette trouvée ou 0 si trouve pas==
NUM_RECETTE.write(nr);
Automaticien privé (de tout)
itasoft@free.fr
itasoft@free.fr
Re: Recettes sur Vijeo-designer.
attention, il y a le risque de collision du hashcode qui n'est pas géré dans ton programme.
2 chaines de caractères différentes peuvent donner le même hashcode (collision) --> oui je sais, 1 chance sur 4 milliards, mais ça arrive plus souvent qu'on le croit
donc il faut comparer dans un premier temps le hashcode (rapide) puis les chaines de caractères (lent) en cas d'égalité du hashcode.
c'est dommage que le java de Vijeo ne gère pas les HashMap ou HashTable (c'est ce que tu es en train de recréer, plus ou moins).
le principe d'une hashtable, au lieu de faire une recherche linéaire sur un tableau de 100, est de tomber directement sur les bons candidats (pour une taille de 100, seulement 2 ou 3 candidats à tester).
il y a plusieurs façon de faire, mais la plus simple est :
suppose une liste chaînée ou un tableau dynamique (array en java) que tu appelles "bucket" (seau).
suppose un tableau de "bucket" dont la taille de ce tableau est un nombre premier bien choisi (qui se calcule en fonction du volume de données et d'un facteur de charge, mais pour une constante de 100, pourquoi pas 43 ou 89 ou même 101).
au remplissage de ta hashmap, tu ranges le numéro de la recette (opération "push") dans le bucket à l'indice "HashCode" modulo (%) "taille de la map = nombre premier". Sur un bucket donné, il peut y avoir plusieurs recettes (d'où le tableau dynamique ou la liste chaînée), mais rarement bcp.
A la recherche d'une recette, c'est le même principe : tu as le hashcode, donc l'indice du bucket. Le bucket te donnera les 2 / 3 candidats à tester (il n'y en a rarement bcp parce que le choix d'un nombre premier fait que les recettes seront généralement bien réparties).
si ton hashcode est de bonne qualité, tu peux même utiliser un poids binaire (64 ou 128 pour un tableau de 100 valeurs par ex) au lieu d'un nombre premier et calculer l'indice du bucket par un simple masquage (AND 63 ou AND 127).
ceci dit, à faire ça avec Vijeo est impossible (à mon avis)
... et c'est plus de l'informatique que de l'automatisme ...
simplement pour que tu vois l'utilité / l'usage réel du "hashcode" (et une hashmap est très utilisée en info et est très rapide pour une recherche de données - c'est de cette façon que les bases de données gèrent les "index")
@+
2 chaines de caractères différentes peuvent donner le même hashcode (collision) --> oui je sais, 1 chance sur 4 milliards, mais ça arrive plus souvent qu'on le croit
![Cool 8-)](./images/smilies/icon_cool.gif)
donc il faut comparer dans un premier temps le hashcode (rapide) puis les chaines de caractères (lent) en cas d'égalité du hashcode.
c'est dommage que le java de Vijeo ne gère pas les HashMap ou HashTable (c'est ce que tu es en train de recréer, plus ou moins).
le principe d'une hashtable, au lieu de faire une recherche linéaire sur un tableau de 100, est de tomber directement sur les bons candidats (pour une taille de 100, seulement 2 ou 3 candidats à tester).
il y a plusieurs façon de faire, mais la plus simple est :
suppose une liste chaînée ou un tableau dynamique (array en java) que tu appelles "bucket" (seau).
suppose un tableau de "bucket" dont la taille de ce tableau est un nombre premier bien choisi (qui se calcule en fonction du volume de données et d'un facteur de charge, mais pour une constante de 100, pourquoi pas 43 ou 89 ou même 101).
au remplissage de ta hashmap, tu ranges le numéro de la recette (opération "push") dans le bucket à l'indice "HashCode" modulo (%) "taille de la map = nombre premier". Sur un bucket donné, il peut y avoir plusieurs recettes (d'où le tableau dynamique ou la liste chaînée), mais rarement bcp.
A la recherche d'une recette, c'est le même principe : tu as le hashcode, donc l'indice du bucket. Le bucket te donnera les 2 / 3 candidats à tester (il n'y en a rarement bcp parce que le choix d'un nombre premier fait que les recettes seront généralement bien réparties).
si ton hashcode est de bonne qualité, tu peux même utiliser un poids binaire (64 ou 128 pour un tableau de 100 valeurs par ex) au lieu d'un nombre premier et calculer l'indice du bucket par un simple masquage (AND 63 ou AND 127).
ceci dit, à faire ça avec Vijeo est impossible (à mon avis)
![M. Vert :mrgreen:](./images/smilies/icon_mrgreen.gif)
simplement pour que tu vois l'utilité / l'usage réel du "hashcode" (et une hashmap est très utilisée en info et est très rapide pour une recherche de données - c'est de cette façon que les bases de données gèrent les "index")
@+
Re: Recettes sur Vijeo-designer.
une idée que je vais essayer de développer (pas trop le temps, donc en plusieurs parties) :
* mettre en place un "écouteur" sur la variable "_RecipeControlDefault.Status", ainsi un script peut être déclenché dès qu'une opération est effectuée sur les recettes (chargement / sauvegarde ...)
je viens de tester, ça fonctionne bien ; exemple pour un chargement de recettes, le script est appelé avec "Status" à 1025 (bit 10 + bit 0) puis est appelé à nouveau avec "Status" à 0.
pour info, voici la description de la variable "Status" :
ce script servira à actualiser notre propre table d'étiquettes (un tableau de STRING) et le hashcode correspondant qui sera enregistré.
* pour initialiser notre table d'étiquettes, il faut un script au démarrage de l'IHM
celui-ci va lancer le chargement de la première recette (amorçage)
le script à l'écoute de la variable "Status" va stocker l'étiquette et lancer le chargement de la recette suivante (relance) jusqu'à ce qu'il y ait une erreur (on sera arrivé au bout de toutes les recettes, on aura déterminé le nombre total de recettes)
c'est un peu "tordu" comme fonctionnement, mais il n'y a pas le choix vu que la gestion des recettes se programme par "contrat" (ordre puis résultat).
pour le stockage des hashcodes, au lieu d'un tableau de int, j'opterai plutôt pour un STRING (qui est en fait un tableau de CHAR) puis les recherches avec la fonction "indexOf" (quoique le type STRING est limité à 100 caractères ...)
le hashcode sera réduit à une valeur 8 bits (un CHAR).
voilà le programme, affaire à suivre![M. Vert :mrgreen:](./images/smilies/icon_mrgreen.gif)
* mettre en place un "écouteur" sur la variable "_RecipeControlDefault.Status", ainsi un script peut être déclenché dès qu'une opération est effectuée sur les recettes (chargement / sauvegarde ...)
je viens de tester, ça fonctionne bien ; exemple pour un chargement de recettes, le script est appelé avec "Status" à 1025 (bit 10 + bit 0) puis est appelé à nouveau avec "Status" à 0.
pour info, voici la description de la variable "Status" :
ce script servira à actualiser notre propre table d'étiquettes (un tableau de STRING) et le hashcode correspondant qui sera enregistré.
* pour initialiser notre table d'étiquettes, il faut un script au démarrage de l'IHM
celui-ci va lancer le chargement de la première recette (amorçage)
le script à l'écoute de la variable "Status" va stocker l'étiquette et lancer le chargement de la recette suivante (relance) jusqu'à ce qu'il y ait une erreur (on sera arrivé au bout de toutes les recettes, on aura déterminé le nombre total de recettes)
c'est un peu "tordu" comme fonctionnement, mais il n'y a pas le choix vu que la gestion des recettes se programme par "contrat" (ordre puis résultat).
pour le stockage des hashcodes, au lieu d'un tableau de int, j'opterai plutôt pour un STRING (qui est en fait un tableau de CHAR) puis les recherches avec la fonction "indexOf" (quoique le type STRING est limité à 100 caractères ...)
le hashcode sera réduit à une valeur 8 bits (un CHAR).
voilà le programme, affaire à suivre
![M. Vert :mrgreen:](./images/smilies/icon_mrgreen.gif)
- itasoft
- Mi homme - Mi automate
- Messages : 7152
- Enregistré le : 20 oct. 2015, 10:15
- Localisation : Lyon
- Contact :
Re: Recettes sur Vijeo-designer.
slts,
la fonction indexOf() donne la première occurrence trouvée, si on cherche le texte "ABCD" il va aussi trouver le texte "ABCDEFGH"
la fonction indexOf() donne la première occurrence trouvée, si on cherche le texte "ABCD" il va aussi trouver le texte "ABCDEFGH"
Automaticien privé (de tout)
itasoft@free.fr
itasoft@free.fr
Re: Recettes sur Vijeo-designer.
posons les bases:
* une étiquette est une chaine de 32 caractères maxi
* on ne travaille que sur un seul groupe de recettes
* il n'y a que 100 recettes maxi (la limite de Vijeo est 256 par groupe, mais comme les chaines de caractères ne peuvent faire que 100 caractères de longueur ...)
les variables à déclarer:
* un tableau "Etiquettes" de 100 * STRING de 32 caractères, en stockage interne, non persistant
* un STRING "HashCodes" de 100 caractères, en stockage interne, non persistant
détails sur le hashcode:
pour chaque étiquette de recette un code de hachage est calculé (java fait tout le boulot via la méthode "hashCode")
pour des raisons pratiques, ce code sera stocké dans une chaine de caractères, la chaine "HashCodes".
un caractère correspondra à une recette (donc 5ème caractère = code de hachage de la recette 5 ...)
ce code de hachage est initialement un entier (int), il faut le convertir en caractère (char)
la valeur "hash" sera entre 1 et 253.
127 est un nombre premier, ce qui répartira bien la plage initiale.
je me réserve la valeur 0 pour indiquer une recette pas encore initialisée.
le script à exécuter au démarrage de l'IHM:
le script au changement de la variable "Status" (cf post précédent) :
bon, il reste à débugger, tester, simplifier ... à suivre
* une étiquette est une chaine de 32 caractères maxi
* on ne travaille que sur un seul groupe de recettes
* il n'y a que 100 recettes maxi (la limite de Vijeo est 256 par groupe, mais comme les chaines de caractères ne peuvent faire que 100 caractères de longueur ...)
les variables à déclarer:
* un tableau "Etiquettes" de 100 * STRING de 32 caractères, en stockage interne, non persistant
* un STRING "HashCodes" de 100 caractères, en stockage interne, non persistant
détails sur le hashcode:
pour chaque étiquette de recette un code de hachage est calculé (java fait tout le boulot via la méthode "hashCode")
pour des raisons pratiques, ce code sera stocké dans une chaine de caractères, la chaine "HashCodes".
un caractère correspondra à une recette (donc 5ème caractère = code de hachage de la recette 5 ...)
ce code de hachage est initialement un entier (int), il faut le convertir en caractère (char)
Code : Tout sélectionner
char hash = (char)(etiquette.hashCode() % 127 + 127);
127 est un nombre premier, ce qui répartira bien la plage initiale.
je me réserve la valeur 0 pour indiquer une recette pas encore initialisée.
le script à exécuter au démarrage de l'IHM:
Code : Tout sélectionner
StringBuffer buffer = new StringBuffer();
buffer.setLength(100); // remplissage par '\u0000'
HashCodes.write(buffer.toString());
_RecipeControlDefault.RecipeNumber.write(1); // recette n° 1
_RecipeControlDefault.Operation.write(4); // commande "charger"
Code : Tout sélectionner
int status = _RecipeControlDefault.Status.getIntValue();
if ((status & 1) == 0) // opération terminée
{
if ((status & 2) == 0) // pas d'erreur
{
int index = _RecipeControlDefault.RecipeNumber.getIntValue() - 1;
String etiquette = _RecipeControlDefault.RecipeLabel.getStringValue();
Etiquettes[index].write(etiquette); // mise à jour de notre table
char hash = (char)(etiquette.hashCode() % 127 + 127); // calcul du code de hachage
StringBuffer buffer = new StringBuffer(HashCodes.getStringValue());
buffer.setCharAt(index, hash); // enregistrement du code de hachage
HashCodes.write(buffer.toString());
}
else if (_RecipeControlDefault.Error.getIntValue() == 4) // indice erroné
{
int index = _RecipeControlDefault.RecipeNumber.getIntValue() - 1;
String str = HashCodes.getStringValue();
if (str.length() > index)
{
// raccourcissement de la chaine
StringBuffer buffer = new StringBuffer(str);
buffer.setLength(index);
HashCodes.write(buffer.toString());
}
}
// encore une recette à initialiser ?
int index = HashCodes.getStringValue().indexOf(0);
if (index >= 0)
{
_RecipeControlDefault.RecipeNumber.write(index + 1); // recette à charger
_RecipeControlDefault.Operation.write(4); // opération chargement
}
}
Re: Recettes sur Vijeo-designer.
c'est pour ça qu'il y a sa petite soeur :la fonction indexOf() donne la première occurrence trouvée, si on cherche le texte "ABCD" il va aussi trouver le texte "ABCDEFGH"
et on l'utilise comme ceci :indexOf(String str,int fromIndex)
Retourne la position de l'index dans cette chaîne de la première occurrence de la sous chaîne en commençant par la position d'index définie.
paramètre1 : Chaîne
paramètre2 : entier
retour : entier
Code : Tout sélectionner
int index = -1;
while ((index = str.indexOf(32, index + 1)) >= 0)
{
// ici index est positionné à chaque caractère "espace" (code 32)
}
Code : Tout sélectionner
char hash = (char)(etiquette.hashCode() % 127 + 127); // etiquette est le nom de la recette qu'on cherche
int index = -1;
String str = HashCodes.getStringValue();
while ((index = str.indexOf(hash, index + 1)) >= 0 && !Etiquettes[index].getStringValue().equals(etiquette));
// ici index = -1 si recette pas trouvée, sinon index = (n° de recette - 1)
Modifié en dernier par steph68 le 24 nov. 2015, 23:56, modifié 3 fois.
Re: Recettes sur Vijeo-designer.
aux premiers essais:
* l'amorce ne fonctionne pas (le script est bien exécuté mais pour une raison obscure, Vijeo ne charge pas la 1ère recette ou il n'appelle pas le script "écouteur")
* si je fais une amorce manuelle, je vois bien les recettes défiler à toute allure et le tableau se remplir correctement (étiquette + hashcode)
* le hic, c'est que de temps en temps, ça s'arrête en plein milieu (le gestionnaire de recettes doit retourner une erreur ou je ne sais quoi ...) - un coup c'est nickel, un coup ça plante au bout de X recettes traitées ...
donc ce n'est pas encore au point ...
et ça sent les "évènements" de Vijeo pas super fiable (c'est déjà du vécu)... à creuser
@+
* l'amorce ne fonctionne pas (le script est bien exécuté mais pour une raison obscure, Vijeo ne charge pas la 1ère recette ou il n'appelle pas le script "écouteur")
* si je fais une amorce manuelle, je vois bien les recettes défiler à toute allure et le tableau se remplir correctement (étiquette + hashcode)
* le hic, c'est que de temps en temps, ça s'arrête en plein milieu (le gestionnaire de recettes doit retourner une erreur ou je ne sais quoi ...) - un coup c'est nickel, un coup ça plante au bout de X recettes traitées ...
donc ce n'est pas encore au point ...
![Diable :evil:](./images/smilies/icon_evil.gif)
@+