s7-server
Version:
TypeScript S7 PLC Server Simulator
162 lines • 5.44 kB
JavaScript
/**
* S7 Server Example
* Demonstrates a production-ready S7 server implementation
*
* This example creates an S7 server with pre-configured memory areas:
* - DB1: Data Block 1 (100 bytes)
* - DB2: Data Block 2 (200 bytes)
* - PE: Process Inputs (64 bytes)
* - PA: Process Outputs (64 bytes)
* - MK: Merker/Memory (32 bytes)
*/
Object.defineProperty(exports, "__esModule", { value: true });
// Node.js built-in modules
const buffer_1 = require("buffer");
// Internal modules
const index_1 = require("../index");
/**
* Configuration constants
*/
const SERVER_CONFIG = {
localPort: 102,
workInterval: 100,
pduRequest: 960,
maxClients: 8,
resourceless: false,
eventMask: 0xffff // All events
};
/**
* Memory area configurations
*/
const MEMORY_AREAS = {
DB1: { area: index_1.S7Area.DB, index: 1, size: 100 },
DB2: { area: index_1.S7Area.DB, index: 2, size: 200 },
PE: { area: index_1.S7Area.PE, index: 0, size: 64 },
PA: { area: index_1.S7Area.PA, index: 0, size: 64 },
MK: { area: index_1.S7Area.MK, index: 0, size: 32 }
};
/**
* Main server function
*/
async function main() {
let server = null;
const inputTimer = null;
try {
// Create server instance
server = new index_1.S7Server(SERVER_CONFIG);
// Register memory areas
await registerMemoryAreas(server);
// Start the server
await startServer(server);
// Set up graceful shutdown
setupGracefulShutdown(server, inputTimer);
}
catch (error) {
console.error('Fatal error:', error);
await cleanup(server, inputTimer);
process.exit(1);
}
}
/**
* Register all memory areas with the server
*/
async function registerMemoryAreas(server) {
// Register Data Blocks
const db1Buffer = buffer_1.Buffer.alloc(MEMORY_AREAS.DB1.size).fill(0);
await server.registerArea(MEMORY_AREAS.DB1.area, MEMORY_AREAS.DB1.index, db1Buffer);
const db2Buffer = buffer_1.Buffer.alloc(MEMORY_AREAS.DB2.size).fill(0);
await server.registerArea(MEMORY_AREAS.DB2.area, MEMORY_AREAS.DB2.index, db2Buffer);
// Register Process Inputs
const peBuffer = buffer_1.Buffer.alloc(MEMORY_AREAS.PE.size).fill(0);
await server.registerArea(MEMORY_AREAS.PE.area, MEMORY_AREAS.PE.index, peBuffer);
// Register Process Outputs
const paBuffer = buffer_1.Buffer.alloc(MEMORY_AREAS.PA.size).fill(0);
await server.registerArea(MEMORY_AREAS.PA.area, MEMORY_AREAS.PA.index, paBuffer);
// Register Merker/Memory
const mkBuffer = buffer_1.Buffer.alloc(MEMORY_AREAS.MK.size).fill(0);
await server.registerArea(MEMORY_AREAS.MK.area, MEMORY_AREAS.MK.index, mkBuffer);
}
/**
* Start the server with proper error handling
*/
async function startServer(server) {
try {
const started = await server.start();
if (!started) {
throw new Error('Failed to start server - unknown reason');
}
const port = server.getParam(index_1.ServerParam.LocalPort);
console.log(`S7 Server started successfully on port ${port}`);
// Set CPU status to RUN
server.setCpuStatus(index_1.CpuStatus.Run);
// Ensure resourceless mode is disabled
server.setResourceless(false);
// Demonstrate the read() function
await demonstrateReadFunction(server);
}
catch (error) {
if (error && typeof error === 'object' && 'code' in error && error.code === 'EADDRINUSE') {
const port = server.getParam(index_1.ServerParam.LocalPort);
throw new Error(`Port ${port} is already in use. Please stop other servers or use a different port.`);
}
else {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Error starting server: ${errorMessage}`);
}
}
}
/**
* Set up graceful shutdown handling
*/
function setupGracefulShutdown(server, inputTimer) {
process.on('SIGINT', async () => {
console.log('\nShutting down server...');
await cleanup(server, inputTimer);
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('\nShutting down server...');
await cleanup(server, inputTimer);
process.exit(0);
});
}
/**
* Demonstrate the read() function with various address formats
*/
async function demonstrateReadFunction(server) {
console.log('Testing read() function...');
try {
// Test a few key address formats
const db1Value = await server.read('DB1');
const bitValue = await server.read('I1.0');
const byteValue = await server.read('IB0');
const wordValue = await server.read('IW16');
console.log(`Sample reads - DB1: ${db1Value}, I1.0: ${bitValue}, IB0: ${byteValue}, IW16: ${wordValue}`);
}
catch (error) {
console.error('Error during read demonstration:', error);
}
}
/**
* Clean up resources
*/
async function cleanup(server, inputTimer) {
try {
if (inputTimer) {
clearInterval(inputTimer);
}
if (server) {
await server.stop();
}
}
catch (error) {
console.error('Error during cleanup:', error);
}
}
// Run the example with proper error handling
main().catch(error => {
console.error('Unhandled error:', error);
process.exit(1);
});
//# sourceMappingURL=server.js.map
;