View Javadoc
1   package net.sf.mbus4j.decoder;
2   
3   /*
4    * #%L
5    * mbus4j-core
6    * %%
7    * Copyright (C) 2009 - 2014 MBus4J
8    * %%
9    * mbus4j - Drivers for the M-Bus protocol - http://mbus4j.sourceforge.net/
10   * Copyright (C) 2009-2014, mbus4j.sf.net, and individual contributors as indicated
11   * by the @authors tag. See the copyright.txt in the distribution for a
12   * full listing of individual contributors.
13   * 
14   * This is free software; you can redistribute it and/or modify it
15   * under the terms of the GNU General Public License as
16   * published by the Free Software Foundation; either version 3 of
17   * the License, or (at your option) any later version.
18   * 
19   * This software is distributed in the hope that it will be useful,
20   * but WITHOUT ANY WARRANTY; without even the implied warranty of
21   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22   * Lesser General Public License for more details.
23   * 
24   * You should have received a copy of the GNU Lesser General Public
25   * License along with this software; if not, write to the Free
26   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
28   * #L%
29   */
30  import java.util.Arrays;
31  import java.util.logging.Level;
32  import java.util.logging.Logger;
33  import net.sf.mbus4j.NotSupportedException;
34  import net.sf.mbus4j.dataframes.LongFrame;
35  import net.sf.mbus4j.dataframes.MBusMedium;
36  import net.sf.mbus4j.dataframes.datablocks.ByteDataBlock;
37  import net.sf.mbus4j.dataframes.datablocks.DataBlock;
38  import net.sf.mbus4j.dataframes.datablocks.DateAndTimeDataBlock;
39  import net.sf.mbus4j.dataframes.datablocks.DateDataBlock;
40  import net.sf.mbus4j.dataframes.datablocks.EnhancedIdentificationDataBlock;
41  import net.sf.mbus4j.dataframes.datablocks.IntegerDataBlock;
42  import net.sf.mbus4j.dataframes.datablocks.LongDataBlock;
43  import net.sf.mbus4j.dataframes.datablocks.RawDataBlock;
44  import net.sf.mbus4j.dataframes.datablocks.RealDataBlock;
45  import net.sf.mbus4j.dataframes.datablocks.ShortDataBlock;
46  import net.sf.mbus4j.dataframes.datablocks.StringDataBlock;
47  import net.sf.mbus4j.dataframes.datablocks.dif.DataFieldCode;
48  import net.sf.mbus4j.dataframes.datablocks.dif.FunctionField;
49  import net.sf.mbus4j.dataframes.datablocks.dif.VariableLengthType;
50  import net.sf.mbus4j.dataframes.datablocks.vif.ObjectAction;
51  import net.sf.mbus4j.dataframes.datablocks.vif.Vif;
52  import net.sf.mbus4j.dataframes.datablocks.vif.VifAscii;
53  import net.sf.mbus4j.dataframes.datablocks.vif.VifFB;
54  import net.sf.mbus4j.dataframes.datablocks.vif.VifFC;
55  import net.sf.mbus4j.dataframes.datablocks.vif.VifeFC;
56  import net.sf.mbus4j.dataframes.datablocks.vif.VifFD;
57  import net.sf.mbus4j.dataframes.datablocks.vif.VifManufacturerSpecific;
58  import net.sf.mbus4j.dataframes.datablocks.vif.VifPrimary;
59  import net.sf.mbus4j.dataframes.datablocks.vif.Vife;
60  import net.sf.mbus4j.dataframes.datablocks.vif.VifeError;
61  import net.sf.mbus4j.dataframes.datablocks.vif.VifeManufacturerSpecific;
62  import net.sf.mbus4j.dataframes.datablocks.vif.VifePrimary;
63  import net.sf.mbus4j.log.LogUtils;
64  
65  /**
66   *
67   * @author arnep@users.sourceforge.net
68   * @version $Id: VariableDataBlockDecoder.java 157 2016-05-06 07:42:00Z arnep $
69   */
70  public class VariableDataBlockDecoder {
71  
72      private void createDataBlock() {
73          try {
74              db = DataBlock.getDataBlockClass(vif, vifes, dfc, variableLengthType).newInstance();
75          } catch (IllegalAccessException | InstantiationException ex) {
76              throw new RuntimeException(ex);
77          }
78          db.setVif(vif);
79          db.setDataFieldCode(dfc);
80          if (vifes == null) {
81              db.clearVifes();
82          } else {
83              for (Vife vife : vifes) {
84                  db.addVife(vife);
85              }
86          }
87          db.setStorageNumber(storageNumber);
88          db.setTariff(tariff);
89          db.setSubUnit(subUnit);
90          db.setFunctionField(functionField);
91          db.setAction(objectAction);
92      }
93  
94      public enum DecodeState {
95  
96          WAIT_FOR_INIT,
97          DIF,
98          DIFE,
99          VIF,
100         VIF_FB,
101         VIF_FC,
102         VIF_FD,
103         VIFE,
104         MAN_SPEC_VIFE,
105         VIFE_FC,
106         ASCII_VIF_LENGTH,
107         ASCII_VIF_COLLECT,
108         SET_VARIABLE_LENGTH,
109         COLLECTING_VALUE,
110         ERROR,
111         RESULT_AVAIL;
112     }
113     private final static Logger LOG = LogUtils.getDecoderLogger();
114     private DecodeState ds = DecodeState.WAIT_FOR_INIT;
115     private int difePos;
116     private ObjectAction objectAction;
117     private DataFieldCode dfc;
118     private VariableLengthType variableLengthType;
119     private FunctionField functionField;
120     private long storageNumber;
121     private int tariff;
122     private short subUnit;
123     private Vif vif;
124     private Vife[] vifes;
125     private DataBlock db;
126     private LongFrame frame;
127     private final Stack stack = new Stack();
128 
129     public VariableDataBlockDecoder() {
130         super();
131     }
132 
133     public DecodeState addByte(final byte b, final int bytesLeft) {
134         switch (ds) {
135             case DIF:
136                 decodeDif(b, bytesLeft);
137                 difePos = 0;
138                 return ds;
139             case DIFE:
140                 decodeDIFE(b, difePos++);
141                 return ds;
142             case VIF:
143                 decodeVIF(b);
144                 break;
145             case ASCII_VIF_LENGTH:
146                 stack.init(b & 0xFF);
147                 setState(DecodeState.ASCII_VIF_COLLECT);
148                 return ds;
149             case ASCII_VIF_COLLECT:
150                 stack.push(b);
151 
152                 if (stack.isFull()) {
153                     ((VifAscii) vif).setValue(stack.popString());
154                     startCollectingValue();
155                 }
156                 return ds;
157             case VIF_FB:
158                 decodeVifExtention_FB(b);
159                 return ds;
160             case VIF_FC:
161                 decodeVifExtention_FC(b);
162                 return ds;
163             case VIF_FD:
164                 decodeVifExtention_FD(b);
165                 return ds;
166             case VIFE:
167                 decodeVife(b);
168                 return ds;
169             case MAN_SPEC_VIFE:
170                 decodeManSpecVife(b);
171                 return ds;
172             case VIFE_FC:
173                 decodeVifeExtension_FC(b);
174                 return ds;
175             case COLLECTING_VALUE:
176                 stack.push(b);
177                 if (stack.isFull()) {
178                     decodeValueFromStack();
179                 }
180                 return ds;
181             case SET_VARIABLE_LENGTH:
182                 if ((b & 0xFF) < 0xBF) {
183                     variableLengthType = VariableLengthType.STRING;
184                     startCollectingValue((b & 0xFF));
185                 } else if ((b & 0xFF) < 0xCF) {
186                     variableLengthType = VariableLengthType.BIG_DECIMAL;
187                     startCollectingValue((b & 0xFF) - 0xC0);
188                 } else if ((b & 0xFF) < 0xDF) {
189                     variableLengthType = VariableLengthType.BIG_DECIMAL;
190                     startCollectingValue((b & 0xFF) - 0xD0);
191                 } else if ((b & 0xFF) < 0xEF) {
192                     throw new DecodeException("binary number ???? how to decode");
193                 } else if ((b & 0xFF) < 0xFA) {
194                     throw new DecodeException("floating point to be defined");
195                 } else {
196                     throw new DecodeException(String.format("reserved: 0x%02x ", b & 0xFF));
197                 }
198                 return ds;
199             default:
200                 LOG.log(Level.SEVERE, "Unknown state: {0}", ds);
201                 setState(DecodeState.ERROR);
202         }
203         return ds;
204     }
205 
206     public void reset() {
207         stack.clear();
208         setState(DecodeState.WAIT_FOR_INIT);
209     }
210 
211     private void decodeDif(final byte b, int bytesLeft) {
212         switch (b & 0xFF) {
213             case 0x0F:
214                 dfc = DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET;
215                 if (bytesLeft == 0) {
216                     createDataBlock();
217                     setState(DecodeState.RESULT_AVAIL);
218                 } else {
219                     startCollectingValue(bytesLeft);
220                 }
221                 return;
222             case 0x1F:
223                 dfc = DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS;
224                 if (bytesLeft == 0) {
225                     createDataBlock();
226                     setState(DecodeState.RESULT_AVAIL);
227                 } else {
228                     startCollectingValue(bytesLeft);
229                 }
230                 return;
231             case 0x2F:
232                 // Skip idlefiller next byte is DIF
233                 return;
234             case 0x3F:
235             case 0x4F:
236             case 0x5F:
237             case 0x6F:
238                 setState(DecodeState.ERROR);
239                 throw new DecodeException(String.format("DIF reserved 0x%02x ", b & 0xFF)); // Reserverd,
240             case 0x7F:
241                 dfc = DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST;
242                 break;
243             default:
244 
245                 // decode data field
246                 switch (b & 0x0F) {
247                     case 0x00:
248                         dfc = DataFieldCode.NO_DATA;
249                         break;
250                     case 0x01:
251                         dfc = DataFieldCode._8_BIT_INTEGER;
252                         break;
253                     case 0x02:
254                         dfc = DataFieldCode._16_BIT_INTEGER;
255                         break;
256                     case 0x03:
257                         dfc = DataFieldCode._24_BIT_INTEGER;
258                         break;
259                     case 0x04:
260                         dfc = DataFieldCode._32_BIT_INTEGER;
261                         break;
262                     case 0x05:
263                         dfc = DataFieldCode._32_BIT_REAL;
264                         break;
265                     case 0x06:
266                         dfc = DataFieldCode._48_BIT_INTEGER;
267                         break;
268                     case 0x07:
269                         dfc = DataFieldCode._64_BIT_INTEGER;
270                         break;
271                     case 0x08:
272                         dfc = DataFieldCode.SELECTION_FOR_READOUT;
273                         break;
274                     case 0x09:
275                         dfc = DataFieldCode._2_DIGIT_BCD;
276                         break;
277                     case 0x0A:
278                         dfc = DataFieldCode._4_DIGIT_BCD;
279                         break;
280                     case 0x0B:
281                         dfc = DataFieldCode._6_DIGIT_BCD;
282                         break;
283                     case 0x0C:
284                         dfc = DataFieldCode._8_DIGIT_BCD;
285                         break;
286                     case 0x0D:
287                         dfc = DataFieldCode.VARIABLE_LENGTH;
288                         break;
289                     case 0x0E:
290                         dfc = DataFieldCode._12_DIGIT_BCD;
291                         break;
292                     case 0x0F:
293                         setState(DecodeState.ERROR);
294                         throw new NotSupportedException("data field 0x0f not supported");
295                     default:
296                         setState(DecodeState.ERROR);
297                         throw new NotSupportedException(String.format("data field of DIF 0x%02x not supported", b & 0xFF));
298                 }
299 
300                 // decode function field
301                 switch (b & 0x30) {
302                     case 0x00:
303                         functionField = FunctionField.INSTANTANEOUS_VALUE;
304                         break;
305                     case 0x10:
306                         functionField = FunctionField.MAXIMUM_VALUE;
307                         break;
308                     case 0x20:
309                         functionField = FunctionField.MINIMUM_VALUE;
310                         break;
311                     case 0x30:
312                         functionField = FunctionField.VALUE_DURING_ERROR_STATE;
313                         break;
314                     default:
315                         throw new NotSupportedException("Function field");
316                 }
317         }
318 
319         storageNumber = (b >> 6) & 0x01;
320 
321         if ((b & Decoder.EXTENTION_BIT) == Decoder.EXTENTION_BIT) {
322             setState(DecodeState.DIFE);
323         } else if (bytesLeft == 0) {
324             createDataBlock();
325             setState(DecodeState.RESULT_AVAIL);
326         } else {
327             setState(DecodeState.VIF);
328         }
329     }
330 
331     private void decodeDIFE(final byte b, int dFIEIndex) {
332         storageNumber |= (long) (b & 0x0F) << (1 + (dFIEIndex * 4));
333         tariff |= ((b >> 4) & 0x03) << (dFIEIndex * 2);
334         subUnit |= (short) (((b >> 6) & 0x01) << dFIEIndex);
335 
336         if ((b & Decoder.EXTENTION_BIT) != Decoder.EXTENTION_BIT) {
337             setState(DecodeState.VIF);
338         }
339     }
340 
341     private void decodeEnhancedIdentificationDataBlock(EnhancedIdentificationDataBlock db) {
342         db.setMedium(MBusMedium.valueOf(stack.popByte()));
343         db.setVersion(stack.popByte());
344         db.setMan(stack.popMan());
345         db.setId(stack.popBcdInteger(8));
346     }
347 
348     private void decodeValueFromStack() {
349         createDataBlock();
350         switch (dfc) {
351             case NO_DATA:
352                 break;
353 
354             case _8_BIT_INTEGER:
355                 ((ByteDataBlock) db).setValue(stack.popByte());
356 
357                 break;
358 
359             case _2_DIGIT_BCD:
360                 ((ByteDataBlock) db).setBcdError(stack.peekBcdError(2));
361 
362                 if (((ByteDataBlock) db).getBcdError() != null) {
363                     stack.popBcdByte();
364                 } else {
365                     ((ByteDataBlock) db).setValue(stack.popBcdByte());
366                 }
367 
368                 break;
369 
370             case _16_BIT_INTEGER:
371 
372                 if (db instanceof DateDataBlock) {
373                     ((DateDataBlock) db).setValue(stack.popDate());
374                 } else {
375                     ((ShortDataBlock) db).setValue(stack.popShort());
376                 }
377 
378                 break;
379 
380             case _4_DIGIT_BCD:
381                 ((ShortDataBlock) db).setBcdError(stack.peekBcdError(4));
382 
383                 if (((ShortDataBlock) db).getBcdError() != null) {
384                     stack.popBcdShort(4);
385                 } else {
386                     ((ShortDataBlock) db).setValue(stack.popBcdShort(4));
387                 }
388 
389                 break;
390 
391             case _24_BIT_INTEGER:
392                 ((IntegerDataBlock) db).setValue(stack.popInteger(3));
393 
394                 break;
395 
396             case _6_DIGIT_BCD:
397                 ((IntegerDataBlock) db).setBcdError(stack.peekBcdError(6));
398 
399                 if (((IntegerDataBlock) db).getBcdError() != null) {
400                     stack.popBcdInteger(6);
401                 } else {
402                     ((IntegerDataBlock) db).setValue(stack.popBcdInteger(6));
403                 }
404 
405                 break;
406 
407             case _32_BIT_INTEGER:
408 
409                 if (db instanceof DateAndTimeDataBlock) {
410                     DateAndTimeDataBlock d = ((DateAndTimeDataBlock) db);
411                     d.setValid(stack.peekIsTimestampValid());
412                     d.setSummerTime(stack.peekIsTimestampSummertime());
413                     d.setRes1(stack.peekIsTimestampRes1());
414                     d.setRes2(stack.peekIsTimestampRes2());
415                     d.setRes3(stack.peekIsTimestampRes3());
416                     d.setValue(stack.popTimeStamp());
417                 } else {
418                     ((IntegerDataBlock) db).setValue(stack.popInteger());
419                 }
420 
421                 break;
422 
423             case _8_DIGIT_BCD:
424 
425                 if (db instanceof EnhancedIdentificationDataBlock) {
426                     ((EnhancedIdentificationDataBlock) db).setId(stack.popBcdInteger(8));
427                 } else {
428                     ((IntegerDataBlock) db).setBcdError(stack.peekBcdError(8));
429 
430                     if (((IntegerDataBlock) db).getBcdError() != null) {
431                         stack.popBcdInteger(8);
432                     } else {
433                         ((IntegerDataBlock) db).setValue(stack.popBcdInteger(8));
434                     }
435                 }
436 
437                 break;
438 
439             case _32_BIT_REAL:
440                 ((RealDataBlock) db).setValue(stack.popFloat());
441 
442                 break;
443 
444             case _48_BIT_INTEGER:
445                 ((LongDataBlock) db).setValue(stack.popLong(6));
446 
447                 break;
448 
449             case _12_DIGIT_BCD:
450                 ((LongDataBlock) db).setBcdError(stack.peekBcdError(12));
451 
452                 if (((LongDataBlock) db).getBcdError() != null) {
453                     stack.popBcdInteger(12);
454                 } else {
455                     ((LongDataBlock) db).setValue(stack.popBcdLong(12));
456                 }
457 
458                 break;
459 
460             case _64_BIT_INTEGER:
461 
462                 if (db instanceof EnhancedIdentificationDataBlock) {
463                     decodeEnhancedIdentificationDataBlock((EnhancedIdentificationDataBlock) db);
464                 } else {
465                     ((LongDataBlock) db).setValue(stack.popLong());
466                 }
467 
468                 break;
469 
470             case VARIABLE_LENGTH:
471 
472                 if (db instanceof RawDataBlock) {
473                     ((RawDataBlock) db).setValue(stack.popBytes());
474                 } else if (db instanceof StringDataBlock) {
475                     ((StringDataBlock) db).setValue(stack.popString());
476                 } else {
477                     // TODO BIG DECIMAL and binray
478                     throw new RuntimeException("decode variable lenght " + db.getClass().getName());
479                 }
480 
481                 break;
482 
483             case SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET:
484             case SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS:
485                 ((RawDataBlock) db).setValue(stack.popBytes());
486 
487                 break;
488 
489             default:
490                 throw new RuntimeException("decode data value" + db.getDataFieldCode());
491         }
492 
493         stack.clear();
494         setState(DecodeState.RESULT_AVAIL);
495     }
496 
497     /**
498      * see chapter 8.4.3
499      *
500      * @param b b will be expanded to int, so clear the sign, wich will be
501      * nagative in the case extention bit is set
502      */
503     private void decodeVIF(final byte b) {
504         switch (b & 0xFF) {
505             case 0x7C:
506                 //Vif is ASCII coded (length in first/next byte)
507                 stack.clear();
508                 vif = new VifAscii();
509                 setState(DecodeState.ASCII_VIF_LENGTH);
510                 return;
511 
512             case 0x7E:
513                 vif = VifPrimary.READOUT_SELECTION;
514                 break;
515 
516             case 0x7F:
517                 vif = new VifManufacturerSpecific();
518                 break;
519 
520             case 0xFB:
521                 // decode vife table 8.4.4 b
522                 setState(DecodeState.VIF_FB);
523                 return;
524 
525             case 0xFC:
526                 setState(DecodeState.VIF_FC);
527                 return;
528 
529             case 0xFD:
530                 // decode vife table 8.4.4 a
531                 setState(DecodeState.VIF_FD);
532                 return;
533 
534             case 0xFF:
535                 vif = new VifManufacturerSpecific();
536                 setState(DecodeState.MAN_SPEC_VIFE);
537                 return;
538 
539             default:
540                 vif = VifPrimary.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
541 
542         }
543 
544         goFromVifOrVife(b);
545     }
546 
547     private void decodeManSpecVife(final byte b) {
548         // Extended VID chapter 8.4.5
549         switch (frame.getControlCode()) {
550             case RSP_UD:
551                 Vife vife = new VifeManufacturerSpecific(b);
552 
553                 if (vifes == null) {
554                     vifes = new Vife[1];
555                 } else {
556                     vifes = Arrays.copyOf(vifes, vifes.length + 1);
557                 }
558                 vifes[vifes.length - 1] = vife;
559 
560                 break;
561 
562             case SND_UD:
563                 objectAction = ObjectAction.valueOf(b);
564 
565                 break;
566 
567             default:
568                 setState(DecodeState.ERROR);
569                 throw new NotSupportedException(String.format(
570                         "Dont know how to handele Control code %s ",
571                         frame.getControlCode()));
572         }
573 
574         goFromVifOrVifeManSpec(b);
575     }
576 
577     private void decodeVife(final byte b) {
578         // Extended VID chapter 8.4.5
579         switch (frame.getControlCode()) {
580             case RSP_UD:
581                 if (0xFC == (b & 0xFF)) {
582                     setState(DecodeState.VIFE_FC);
583                     return;
584                 }
585                 Vife vife;
586 
587                 if ((b & ~Decoder.EXTENTION_BIT) > VifePrimary.CODE_OFFSET) {
588                     vife = VifePrimary.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
589                 } else {
590                     vife = VifeError.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
591                 }
592 
593                 if (vifes == null) {
594                     vifes = new Vife[1];
595                 } else {
596                     vifes = Arrays.copyOf(vifes, vifes.length + 1);
597                 }
598 
599                 vifes[vifes.length - 1] = vife;
600 
601                 if (vife == VifePrimary.MAN_SPEC) {
602                     goFromVifOrVifeManSpec(b);
603                 } else {
604                     goFromVifOrVife(b);
605                 }
606 
607                 break;
608 
609             case SND_UD:
610                 objectAction = ObjectAction.valueOf(b);
611                 goFromVifOrVife(b);
612 
613                 break;
614 
615             default:
616                 setState(DecodeState.ERROR);
617                 throw new NotSupportedException(String.format(
618                         "Dont know how to handele Control code %s ",
619                         frame.getControlCode()));
620         }
621 
622     }
623 
624     private void decodeVifeExtension_FC(final byte b) {
625         // Extended VID chapter 8.4.5
626         switch (frame.getControlCode()) {
627             case RSP_UD:
628                 VifeFC vifeFC = VifeFC.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
629 
630                 if (vifes == null) {
631                     vifes = new Vife[1];
632                 } else {
633                     vifes = Arrays.copyOf(vifes, vifes.length + 1);
634                 }
635                 vifes[vifes.length - 1] = vifeFC;
636 
637                 break;
638 
639             case SND_UD:
640                 objectAction = ObjectAction.valueOf(b);
641 
642                 break;
643 
644             default:
645                 setState(DecodeState.ERROR);
646                 throw new NotSupportedException(String.format(
647                         "Dont know how to handele Control code %s ",
648                         frame.getControlCode()));
649         }
650 
651         goFromVifOrVife(b);
652     }
653 
654     private void decodeVifExtention_FB(final byte b) {
655         // Extended VID chapter 8.4.4 table b
656         vif = VifFB.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
657         goFromVifOrVife(b);
658     }
659 
660     private void decodeVifExtention_FC(final byte b) {
661         //new stuff first seen @ SINUS 
662         vif = VifFC.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
663         goFromVifOrVife(b);
664     }
665 
666     private void decodeVifExtention_FD(final byte b) {
667         // Extended VID chapter 8.4.4 table a
668         vif = VifFD.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
669         goFromVifOrVife(b);
670     }
671 
672     public DataBlock getDataBlock() {
673         return db;
674     }
675 
676     public DecodeState getState() {
677         return ds;
678     }
679 
680     private void goFromVifOrVifeManSpec(final byte b) {
681         if ((b & Decoder.EXTENTION_BIT) == Decoder.EXTENTION_BIT) {
682             setState(DecodeState.MAN_SPEC_VIFE);
683         } else if ((dfc == DataFieldCode.SELECTION_FOR_READOUT) || (dfc == DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST)) {
684             createDataBlock();
685             setState(DecodeState.RESULT_AVAIL);
686         } else {
687             startCollectingValue();
688         }
689     }
690 
691     private void goFromVifOrVife(final byte b) {
692         if ((b & Decoder.EXTENTION_BIT) == Decoder.EXTENTION_BIT) {
693             setState(DecodeState.VIFE);
694         } else if ((dfc == DataFieldCode.SELECTION_FOR_READOUT) || (dfc == DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST)) {
695             createDataBlock();
696             setState(DecodeState.RESULT_AVAIL);
697         } else {
698             startCollectingValue();
699         }
700     }
701 
702     public void init(LongFrame frame) {
703 
704         functionField = null;
705         storageNumber = 0;
706         dfc = null;
707         variableLengthType = null;
708         objectAction = null;
709         tariff = 0;
710         subUnit = 0;
711         vif = null;
712         vifes = null;
713         db = null;
714 
715         setState(DecodeState.DIF);
716         this.frame = frame;
717         stack.clear();
718     }
719 
720     public void setState(DecodeState ds) {
721         if ((ds == DecodeState.RESULT_AVAIL) && (db == null)) {
722             throw new RuntimeException("DB IST NULL");
723         }
724 
725         final DecodeState oldState = this.ds;
726         this.ds = ds;
727 
728         LOG.log(Level.FINEST, "{0} => {1}", new Object[]{oldState, ds});
729     }
730 
731     private void startCollectingValue() {
732         switch (dfc) {
733             case NO_DATA:
734                 stack.clear();
735                 createDataBlock();
736                 setState(DecodeState.RESULT_AVAIL);
737 
738                 return;
739 
740             case _8_BIT_INTEGER:
741             case _2_DIGIT_BCD:
742                 stack.init(1);
743 
744                 break;
745 
746             case _16_BIT_INTEGER:
747             case _4_DIGIT_BCD:
748                 stack.init(2);
749 
750                 break;
751 
752             case _24_BIT_INTEGER:
753             case _6_DIGIT_BCD:
754                 stack.init(3);
755 
756                 break;
757 
758             case _32_BIT_INTEGER:
759             case _8_DIGIT_BCD:
760             case _32_BIT_REAL:
761                 stack.init(4);
762 
763                 break;
764 
765             case _48_BIT_INTEGER:
766             case _12_DIGIT_BCD:
767                 stack.init(6);
768 
769                 break;
770 
771             case _64_BIT_INTEGER:
772                 stack.init(8);
773 
774                 break;
775 
776             case VARIABLE_LENGTH:
777                 setState(DecodeState.SET_VARIABLE_LENGTH);
778 
779                 return;
780 
781             default:
782                 throw new RuntimeException("START COLLECTING VALUE" + dfc);
783         }
784 
785         setState(DecodeState.COLLECTING_VALUE);
786     }
787 
788     private void startCollectingValue(int bytesLeft) {
789         stack.init(bytesLeft);
790         setState(DecodeState.COLLECTING_VALUE);
791     }
792 }