lpcmanager

Retain memory: currently disabled, reverse this change when retain is implemented.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
#based on the plcopen standard.
#
#Copyright (C) 2015: Yvan ROCH
#
#See COPYING file for copyrights details.
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This library is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#General Public License for more details.
#
#You should have received a copy of the GNU General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#-------------------------------------------------------------------------------
# Firmware Updater for the host (the IDE)
#-------------------------------------------------------------------------------
"""
Class which controls the firmware update on the remote PLC
See also TargetFirmwareUpdater
"""
import os
import hashlib
UPDATE_SCRIPT_TIMEOUT = 600
class HostFirmwareUpdater(object):
# Create a new HostFirmwareUpdater
def __init__(self, controller, firmwareImagePath, updateType, chunksSize, dialog):
self.Reset()
self.firmwareImagePath = firmwareImagePath
self.updateType = updateType
self.chunksSize = chunksSize
self.controller = controller
self.dialog = dialog
self.controller.logger.write(_("HostFirmwareUpdater init.\n"))
# Reset HostFirmwareUpdater internal variables
def Reset(self):
self.Running = 0
def update(self):
self.controller.logger.write(_("HostFirmwareUpdater update.\n"))
self.firmwareImageFile = open(self.firmwareImagePath, "rb")
# Read the image file
self.imageData = self.firmwareImageFile.read()
self.firmwareImageFileSize = os.stat(self.firmwareImagePath).st_size
self.controller.logger.write(_("Firmware image %s size: %d\n")%(self.firmwareImagePath, self.firmwareImageFileSize))
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
# Create the necessary files on the target
self._CreateFirmwareImageFileSizeFile()
self._CreateFirmwareImageFileSizeMD5File()
self._CreateFirmwareImageFileMD5File()
# start the update script
status, textError = self.controller._connector.RunUpdateScript(self.updateType)
if not status :
raise Exception(textError)
# The update script is now running: Feeding the update script with firmware image data
self._RunFeedPipe()
def _CreateFirmwareImageFileSizeFile(self):
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
status, textError = self.controller._connector.CreateFirmwareImageFileSizeFile(self.firmwareImageFileSize)
if not status :
raise Exception(textError)
def _CreateFirmwareImageFileSizeMD5File(self):
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
self.firmwareImageFileMD5Size = hashlib.md5("%s\n"%self.firmwareImageFileSize).hexdigest()
self.controller.logger.write(_("Firmware image size md5: %s\n")%(self.firmwareImageFileMD5Size))
status, textError = self.controller._connector.CreateFirmwareImageFileSizeMD5File(self.firmwareImageFileMD5Size)
if not status :
raise Exception(textError)
def _CreateFirmwareImageFileMD5File(self):
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
self.firmwareImageFileMD5 = hashlib.md5(self.imageData).hexdigest()
self.controller.logger.write(_("Firmware image %s md5: %s\n")%(self.firmwareImagePath, self.firmwareImageFileMD5))
status, textError = self.controller._connector.CreateFirmwareImageFileMD5File(self.firmwareImageFileMD5)
if not status :
raise Exception(textError)
def _RunFeedPipe(self):
# Check if a multiple chunks transfer is needed
if self.firmwareImageFileSize <= self.chunksSize :
# Only a single chunk transfer is needed
isLastChunk = True
chunksSize = self.firmwareImageFileSize
self.controller.logger.write(_("Single chunk transfer\n"))
else:
# Multiple chunks transfer is needed
isLastChunk = False
chunksSize = self.chunksSize
self.controller.logger.write(_("Multiple chunks transfer\n"))
# Start the image transfer
transferedBytes = 0
while transferedBytes < self.firmwareImageFileSize:
# User feedback as percentage
keepGoing, _skip = self.dialog.Update(
transferedBytes * 100 / self.firmwareImageFileSize)
if not keepGoing:
status = False
textError = _("Canceled")
raise Exception(textError)
chunkData = self.imageData[transferedBytes:transferedBytes + chunksSize]
status, textError = self.controller._connector.RunFeedPipe(chunkData, isLastChunk, chunksSize)
if not status :
break
transferedBytes = transferedBytes + chunksSize
# Detect if the next chunk is the last chunk
if (self.firmwareImageFileSize - transferedBytes) <= self.chunksSize:
isLastChunk = True
chunksSize = self.firmwareImageFileSize - transferedBytes
# Check the transfer and the update status
if not status :
raise Exception(textError)
else:
self.dialog.Update(100,_("Firmware update successful."))
self.controller.logger.write(_("Firmware update log: \n\n") + textError + "\nFirmware update successful.\n")
def RebootTarget(self):
self.controller._connector.RebootTarget()