plugins/python/plc_python.c
changeset 454 fd316d2babd5
parent 366 cd90e4c10261
child 483 bc26c42d2eec
equal deleted inserted replaced
453:923d036dfa90 454:fd316d2babd5
    88  * FB instance is executed
    88  * FB instance is executed
    89  */
    89  */
    90 void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
    90 void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
    91 {
    91 {
    92 	/* detect rising edge on TRIG to trigger evaluation */
    92 	/* detect rising edge on TRIG to trigger evaluation */
    93 	if(((data__->TRIG && !data__->TRIGM1) ||
    93 	if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) ||
    94 	   /* polling is equivalent to trig on value rather than on rising edge*/
    94 	   /* polling is equivalent to trig on value rather than on rising edge*/
    95 	    (poll && data__->TRIG )) &&
    95 	    (poll && __GET_VAR(data__->TRIG) )) &&
    96 	    /* trig only if not already trigged */
    96 	    /* trig only if not already trigged */
    97 	   data__->TRIGGED == 0){
    97 	    __GET_VAR(data__->TRIGGED) == 0){
    98 		/* mark as trigged */
    98 		/* mark as trigged */
    99 		data__->TRIGGED = 1;
    99 	    __SET_VAR(data__->TRIGGED, 1);
   100 		/* make a safe copy of the code */
   100 		/* make a safe copy of the code */
   101 		data__->PREBUFFER = data__->CODE;
   101 		__SET_VAR(data__->PREBUFFER, __GET_VAR(data__->CODE));
   102 	}
   102 	}
   103 	/* retain value for next rising edge detection */
   103 	/* retain value for next rising edge detection */
   104 	data__->TRIGM1 = data__->TRIG;
   104 	__SET_VAR(data__->TRIGM1, __GET_VAR(data__->TRIG));
   105 
   105 
   106 	/* python thread is not in ? */
   106 	/* python thread is not in ? */
   107 	if( PythonState & PYTHON_LOCKED_BY_PLC){
   107 	if( PythonState & PYTHON_LOCKED_BY_PLC){
   108 		/* if some answer are waiting, publish*/
   108 		/* if some answer are waiting, publish*/
   109 		if(data__->STATE == PYTHON_FB_ANSWERED){
   109 		if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){
   110 			/* Copy buffer content into result*/
   110 			/* Copy buffer content into result*/
   111 			data__->RESULT = data__->BUFFER;
   111 			__SET_VAR(data__->RESULT, __GET_VAR(data__->BUFFER));
   112 			/* signal result presece to PLC*/
   112 			/* signal result presece to PLC*/
   113 			data__->ACK = 1;
   113 			__SET_VAR(data__->ACK, 1);
   114 			/* Mark as free */
   114 			/* Mark as free */
   115 			data__->STATE = PYTHON_FB_FREE;
   115 			__SET_VAR(data__->STATE, PYTHON_FB_FREE);
   116 			/* mark as not trigged */
   116 			/* mark as not trigged */
   117 			if(!poll)
   117 			if(!poll)
   118 				data__->TRIGGED = 0;
   118 			    __SET_VAR(data__->TRIGGED, 0);
   119 			/*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
   119 			/*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
   120 		}else if(poll){
   120 		}else if(poll){
   121 			/* when in polling, no answer == ack down */
   121 			/* when in polling, no answer == ack down */
   122 			data__->ACK = 0;
   122 		    __SET_VAR(data__->ACK, 0);
   123 		}
   123 		}
   124 		/* got the order to act ?*/
   124 		/* got the order to act ?*/
   125 		if(data__->TRIGGED == 1 &&
   125 		if(__GET_VAR(data__->TRIGGED) == 1 &&
   126 		   /* and not already being processed */
   126 		   /* and not already being processed */
   127 		   data__->STATE == PYTHON_FB_FREE)
   127 		   __GET_VAR(data__->STATE) == PYTHON_FB_FREE)
   128 		{
   128 		{
   129 			/* Enter the block in the fifo
   129 			/* Enter the block in the fifo
   130 			/* Don't have to check if fifo cell is free
   130 			/* Don't have to check if fifo cell is free
   131 			 * as fifo size == FB count, and a FB cannot
   131 			 * as fifo size == FB count, and a FB cannot
   132 			 * be requested twice */
   132 			 * be requested twice */
   133 			EvalFBs[Current_PLC_EvalFB] = data__;
   133 			EvalFBs[Current_PLC_EvalFB] = data__;
   134 			/* copy into BUFFER local*/
   134 			/* copy into BUFFER local*/
   135 			data__->BUFFER = data__->PREBUFFER;
   135 			__SET_VAR(data__->BUFFER, __GET_VAR(data__->PREBUFFER));
   136 			/* Set ACK pin to low so that we can set a rising edge on result */
   136 			/* Set ACK pin to low so that we can set a rising edge on result */
   137 			if(!poll){
   137 			if(!poll){
   138 				/* when not polling, a new answer imply reseting ack*/
   138 				/* when not polling, a new answer imply reseting ack*/
   139 				data__->ACK = 0;
   139 			    __SET_VAR(data__->ACK, 0);
   140 			}else{
   140 			}else{
   141 				/* when in polling, acting reset trigger */
   141 				/* when in polling, acting reset trigger */
   142 				data__->TRIGGED = 0;
   142 			    __SET_VAR(data__->TRIGGED, 0);
   143 			}
   143 			}
   144 			/* Mark FB busy */
   144 			/* Mark FB busy */
   145 			data__->STATE = PYTHON_FB_REQUESTED;
   145 			__SET_VAR(data__->STATE, PYTHON_FB_REQUESTED);
   146 			/* Have to wakeup python thread in case he was asleep */
   146 			/* Have to wakeup python thread in case he was asleep */
   147 			PythonState |= PYTHON_MUSTWAKEUP;
   147 			PythonState |= PYTHON_MUSTWAKEUP;
   148 			/*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
   148 			/*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
   149 			/* Get a new line */
   149 			/* Get a new line */
   150 			Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
   150 			Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
   160 	/* take python mutex to prevent changing PLC data while PLC running */
   160 	/* take python mutex to prevent changing PLC data while PLC running */
   161 	LockPython();
   161 	LockPython();
   162 	/* Get current FB */
   162 	/* Get current FB */
   163 	data__ = EvalFBs[Current_Python_EvalFB];
   163 	data__ = EvalFBs[Current_Python_EvalFB];
   164 	if(data__ && /* may be null at first run */
   164 	if(data__ && /* may be null at first run */
   165 	   data__->STATE == PYTHON_FB_PROCESSING){ /* some answer awaited*/
   165 	    __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/
   166 	   	/* If result not None */
   166 	   	/* If result not None */
   167 	   	if(result){
   167 	   	if(result){
   168 			/* Get results len */
   168 			/* Get results len */
   169 			data__->BUFFER.len = strlen(result);
   169 	   	    __SET_VAR(data__->BUFFER, strlen(result), .len);
   170 			/* prevent results overrun */
   170 			/* prevent results overrun */
   171 			if(data__->BUFFER.len > STR_MAX_LEN)
   171 			if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN)
   172 			{
   172 			{
   173 				data__->BUFFER.len = STR_MAX_LEN;
   173 			    __SET_VAR(data__->BUFFER, STR_MAX_LEN, .len );
   174 				/* TODO : signal error */
   174 				/* TODO : signal error */
   175 			}
   175 			}
   176 			/* Copy results to buffer */
   176 			/* Copy results to buffer */
   177 			strncpy(data__->BUFFER.body, result, data__->BUFFER.len);
   177 			strncpy(__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len));
   178 	   	}else{
   178 	   	}else{
   179 	   		data__->BUFFER.len = 0;
   179 	   	    __SET_VAR(data__->BUFFER, 0, .len);
   180 	   	}
   180 	   	}
   181 		/* remove block from fifo*/
   181 		/* remove block from fifo*/
   182 		EvalFBs[Current_Python_EvalFB] = NULL;
   182 		EvalFBs[Current_Python_EvalFB] = NULL;
   183 		/* Mark block as answered */
   183 		/* Mark block as answered */
   184 		data__->STATE = PYTHON_FB_ANSWERED;
   184 		__SET_VAR(data__->STATE, PYTHON_FB_ANSWERED);
   185 		/* Get a new line */
   185 		/* Get a new line */
   186 		Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
   186 		Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
   187 		//printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
   187 		//printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
   188 	}
   188 	}
   189 	/* while next slot is empty */
   189 	/* while next slot is empty */
   190 	while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
   190 	while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
   191 	 	  /* or doesn't contain command */
   191 	 	  /* or doesn't contain command */
   192 	      data__->STATE != PYTHON_FB_REQUESTED)
   192 	      __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED)
   193 	{
   193 	{
   194 		UnLockPython();
   194 		UnLockPython();
   195 		/* wait next FB to eval */
   195 		/* wait next FB to eval */
   196 		//printf("PythonIterator wait\n");
   196 		//printf("PythonIterator wait\n");
   197 		if(WaitPythonCommands()) return NULL;
   197 		if(WaitPythonCommands()) return NULL;
   198 		/*emergency exit*/
   198 		/*emergency exit*/
   199 		if(PythonState & PYTHON_FINISHED) return NULL;
   199 		if(PythonState & PYTHON_FINISHED) return NULL;
   200 		LockPython();
   200 		LockPython();
   201 	}
   201 	}
   202 	/* Mark block as processing */
   202 	/* Mark block as processing */
   203 	data__->STATE = PYTHON_FB_PROCESSING;
   203 	__SET_VAR(data__->STATE, PYTHON_FB_PROCESSING);
   204 	//printf("PythonIterator\n");
   204 	//printf("PythonIterator\n");
   205 	/* make BUFFER a null terminated string */
   205 	/* make BUFFER a null terminated string */
   206 	data__->BUFFER.body[data__->BUFFER.len] = 0;
   206 	__SET_VAR(data__->BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]);
   207 	/* next command is BUFFER */
   207 	/* next command is BUFFER */
   208 	next_command = data__->BUFFER.body;
   208 	next_command = __GET_VAR(data__->BUFFER, .body);
   209 	/* free python mutex */
   209 	/* free python mutex */
   210 	UnLockPython();
   210 	UnLockPython();
   211 	/* return the next command to eval */
   211 	/* return the next command to eval */
   212 	return next_command;
   212 	return next_command;
   213 }
   213 }